diff options
Diffstat (limited to 'source')
124 files changed, 2181 insertions, 731 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 4d1c07836dc..f76cdbc64b7 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -40,11 +40,11 @@ extern "C" { struct ListBase; struct MemFile; -#define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 17 +#define BLENDER_VERSION 246 +#define BLENDER_SUBVERSION 0 -#define BLENDER_MINVERSION 240 -#define BLENDER_MINSUBVERSION 0 +#define BLENDER_MINVERSION 245 +#define BLENDER_MINSUBVERSION 15 int BKE_read_file(char *dir, void *type_r); int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r); diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 46252b310ae..2d7d0e9286f 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -171,4 +171,9 @@ void IDP_FreeProperty(struct IDProperty *prop); /*Unlinks any struct IDProperty<->ID linkage that might be going on.*/ void IDP_UnlinkProperty(struct IDProperty *prop); +#define IDP_Int(prop) (prop->data.val) +#define IDP_Float(prop) (*(float*)&prop->data.val) +#define IDP_String(prop) ((char*)prop->data.pointer) +#define IDP_Array(prop) (prop->data.pointer) + #endif /* _BKE_IDPROP_H */ diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 00a53b3f16e..0dfc8ae6b28 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -91,7 +91,6 @@ typedef struct process { /* parameters, function, storage */ float (*function)(float, float, float); float size, delta; /* cube size, normal delta */ int bounds; /* cube range within lattice */ - MB_POINT start; /* start point on surface */ CUBES *cubes; /* active cubes */ VERTICES vertices; /* surface vertices */ CENTERLIST **centers; /* cube center hash table */ @@ -151,7 +150,7 @@ void add_cube(PROCESS *mbproc, int i, int j, int k, int count); void find_first_points(PROCESS *mbproc, struct MetaBall *mb, int a); void fill_metaball_octal_node(octal_node *node, struct MetaElem *ml, short i); -void subdivide_metaball_octal_node(octal_node *node, float *size, short depth); +void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth); void free_metaball_octal_node(octal_node *node); void init_metaball_octal_tree(int depth); void polygonize(PROCESS *mbproc, struct MetaBall *mb); diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 844f25d51dc..7819919fba8 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -43,6 +43,7 @@ extern "C" { #define FFMPEG_H264 6 #define FFMPEG_XVID 7 #define FFMPEG_FLV 8 +#define FFMPEG_MKV 9 #define FFMPEG_CODEC_MPEG1 0 #define FFMPEG_CODEC_MPEG2 1 @@ -58,6 +59,7 @@ extern "C" { #define FFMPEG_PRESET_SVCD 2 #define FFMPEG_PRESET_VCD 3 #define FFMPEG_PRESET_DV 4 +#define FFMPEG_PRESET_H264 5 struct RenderData; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 81f496e97d6..aca51e56c6e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -621,7 +621,8 @@ void BKE_write_undo(char *name) } } -/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ +/* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation + * Note, ALWAYS call sound_initialize_sounds after BKE_undo_step() */ void BKE_undo_step(int step) { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0db327f6efb..d02a7c0ab9e 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -583,7 +583,7 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas /* this is for float inaccuracy */ if(t < knots[0]) t= knots[0]; - else if(t > knots[opp2]) t= knots[opp2]; /* Valgrind reports an error here, use a nurbs torus and change u/v res to reproduce a crash TODO*/ + else if(t > knots[opp2]) t= knots[opp2]; /* this part is order '1' */ o2 = order + 1; @@ -1476,7 +1476,9 @@ void makeBevelList(Object *ob) else nu= cu->nurb.first; while(nu) { - if(nu->pntsu<=1) { + /* check we are a single point? also check we are not a surface and that the orderu is sane, + * enforced in the UI but can go wrong possibly */ + if(nu->pntsu<2 || ((nu->type & 7)==CU_NURBS && nu->pntsu < nu->orderu)) { bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList"); BLI_addtail(&(cu->bev), bl); bl->nr= 0; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 663c94e5155..3644a50b799 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1241,7 +1241,8 @@ void CustomData_em_copy_data(const CustomData *source, CustomData *dest, if(dest_i >= dest->totlayer) return; /* if we found a matching layer, copy the data */ - if(dest->layers[dest_i].type == source->layers[src_i].type) { + if(dest->layers[dest_i].type == source->layers[src_i].type && + strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) { char *src_data = (char*)src_block + source->layers[src_i].offset; char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 6f5660b2a3f..aa436441056 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -783,7 +783,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) else resolu= nu->resolu; - if(nu->pntsu<2); + if(nu->pntsu<2 || ((nu->type & 7)==CU_NURBS && nu->pntsu < nu->orderu)); else if((nu->type & 7)==CU_BEZIER) { /* count */ @@ -1171,7 +1171,7 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed if ((md->mode & required_mode) != required_mode) continue; if (mti->isDisabled && mti->isDisabled(md)) continue; - if (md->type==eModifierType_Hook || md->type==eModifierType_Softbody) { + if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { preTesselatePoint = md; } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index b493f98b7fb..caabc036290 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -989,8 +989,11 @@ static void stampdata(StampData *stamp_data, int do_prefix) } if (G.scene->r.stamp & R_STAMP_CAMERA) { - if (do_prefix) sprintf(stamp_data->camera, "Camera %s", ((Camera *) G.scene->camera)->id.name+2); - else sprintf(stamp_data->camera, "%s", ((Camera *) G.scene->camera)->id.name+2); + if (G.scene->camera) strcpy(text, ((Camera *) G.scene->camera)->id.name+2); + else strcpy(text, "<none>"); + + if (do_prefix) sprintf(stamp_data->camera, "Camera %s", text); + else sprintf(stamp_data->camera, "%s", text); } else { stamp_data->camera[0] = '\0'; } @@ -1721,31 +1724,38 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) { RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); - if(rr && iuser) { + if(rr) { RenderResult rres; float *rectf; unsigned int *rect; - int channels= 4, layer= iuser->layer; + float dither; + int channels, layer, pass; + + channels= 4; + layer= (iuser)? iuser->layer: 0; + pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; - + dither= G.scene->r.dither_intensity; + /* get compo/seq result by default */ if(rr->rectf && layer==0); else if(rr->layers.first) { - RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer-(rr->rectf?1:0)); + RenderLayer *rl= BLI_findlink(&rr->layers, layer-(rr->rectf?1:0)); if(rl) { /* there's no combined pass, is in renderlayer itself */ - if(iuser->pass==0) { + if(pass==0) { rectf= rl->rectf; } else { - RenderPass *rpass= BLI_findlink(&rl->passes, iuser->pass-1); + RenderPass *rpass= BLI_findlink(&rl->passes, pass-1); if(rpass) { channels= rpass->channels; rectf= rpass->rect; + dither= 0.0f; /* don't dither passes */ } } } @@ -1772,6 +1782,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf->channels= channels; ibuf->zbuf_float= rres.rectz; ibuf->flags |= IB_zbuffloat; + ibuf->dither= dither; ima->ok= IMA_OK_LOADED; return ibuf; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 16916381c95..47c06638807 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -375,7 +375,7 @@ Object *find_basis_mball(Object *basis) #define RTF 7 /* right top far corner */ /* the LBN corner of cube (i, j, k), corresponds with location - * (start.x+(i-0.5)*size, start.y+(j-0.5)*size, start.z+(k-0.5)*size) */ + * (i-0.5)*size, (j-0.5)*size, (k-0.5)*size) */ #define HASHBIT (5) #define HASHSIZE (size_t)(1<<(3*HASHBIT)) /*! < hash table size (32768) */ @@ -836,11 +836,11 @@ CORNER *setcorner (PROCESS* p, int i, int j, int k) c = (CORNER *) new_pgn_element(sizeof(CORNER)); c->i = i; - c->x = p->start.x+((float)i-0.5f)*p->size; + c->x = ((float)i-0.5f)*p->size; c->j = j; - c->y = p->start.y+((float)j-0.5f)*p->size; + c->y = ((float)j-0.5f)*p->size; c->k = k; - c->z = p->start.z+((float)k-0.5f)*p->size; + c->z = ((float)k-0.5f)*p->size; c->value = p->function(c->x, c->y, c->z); c->next = p->corners[index]; @@ -1373,39 +1373,38 @@ void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) nz = abs((out.z - in.z)/mbproc->size); MAXN = MAX3(nx,ny,nz); + if(MAXN!=0.0f) { + dx = (out.x - in.x)/MAXN; + dy = (out.y - in.y)/MAXN; + dz = (out.z - in.z)/MAXN; + + len = 0.0; + while(len<=max_len) { + workp.x += dx; + workp.y += dy; + workp.z += dz; + /* compute value of implicite function */ + tmp_v = mbproc->function(workp.x, workp.y, workp.z); + /* add cube to the stack, when value of implicite function crosses zero value */ + if((tmp_v<0.0 && workp_v>=0.0)||(tmp_v>0.0 && workp_v<=0.0)) { + + /* indexes of CUBE, which includes "first point" */ + c_i= (int)floor(workp.x/mbproc->size); + c_j= (int)floor(workp.y/mbproc->size); + c_k= (int)floor(workp.z/mbproc->size); + + /* add CUBE (with indexes c_i, c_j, c_k) to the stack, + * this cube includes found point of Implicit Surface */ + if (ml->flag & MB_NEGATIVE) + add_cube(mbproc, c_i, c_j, c_k, 2); + else + add_cube(mbproc, c_i, c_j, c_k, 1); + } + len = sqrt((workp.x-in.x)*(workp.x-in.x) + (workp.y-in.y)*(workp.y-in.y) + (workp.z-in.z)*(workp.z-in.z)); + workp_v = tmp_v; - dx = (out.x - in.x)/MAXN; - dy = (out.y - in.y)/MAXN; - dz = (out.z - in.z)/MAXN; - - len = 0.0; - while(len<=max_len) { - workp.x += dx; - workp.y += dy; - workp.z += dz; - /* compute value of implicite function */ - tmp_v = mbproc->function(workp.x, workp.y, workp.z); - /* add cube to the stack, when value of implicite function crosses zero value */ - if((tmp_v<0.0 && workp_v>=0.0)||(tmp_v>0.0 && workp_v<=0.0)) { - - /* indexes of CUBE, which includes "first point" */ - c_i= (int)floor(workp.x/mbproc->size); - c_j= (int)floor(workp.y/mbproc->size); - c_k= (int)floor(workp.z/mbproc->size); - - /* add CUBE (with indexes c_i, c_j, c_k) to the stack, - * this cube includes found point of Implicit Surface */ - if (ml->flag & MB_NEGATIVE) - add_cube(mbproc, c_i, c_j, c_k, 2); - else - add_cube(mbproc, c_i, c_j, c_k, 1); } - len = sqrt((workp.x-in.x)*(workp.x-in.x) + (workp.y-in.y)*(workp.y-in.y) + (workp.z-in.z)*(workp.z-in.z)); - workp_v = tmp_v; } - - mbproc->start.x= mbproc->start.y= mbproc->start.z= 0.0; - } } } @@ -1710,15 +1709,13 @@ void fill_metaball_octal_node(octal_node *node, MetaElem *ml, short i) * +------+------+ * */ -void subdivide_metaball_octal_node(octal_node *node, float *size, short depth) +void subdivide_metaball_octal_node(octal_node *node, float size_x, float size_y, float size_z, short depth) { MetaElem *ml; ml_pointer *ml_p; float x,y,z; int a,i; - if(depth==0) return; - /* create new nodes */ for(a=0;a<8;a++){ node->nodes[a]= MEM_mallocN(sizeof(octal_node),"octal_node"); @@ -1732,45 +1729,71 @@ void subdivide_metaball_octal_node(octal_node *node, float *size, short depth) node->nodes[a]->pos= 0; } - size[0]/=2; size[1]/=2; size[2]/=2; + size_x /= 2; + size_y /= 2; + size_z /= 2; /* center of node */ - node->x= x= node->x_min + size[0]; - node->y= y= node->y_min + size[1]; - node->z= z= node->z_min + size[2]; + node->x = x = node->x_min + size_x; + node->y = y = node->y_min + size_y; + node->z = z = node->z_min + size_z; /* setting up of border points of new nodes */ - node->nodes[0]->x_min= node->x_min; - node->nodes[0]->y_min= node->y_min; - node->nodes[0]->z_min= node->z_min; - - node->nodes[1]->x_min= x; - node->nodes[1]->y_min= node->y_min; - node->nodes[1]->z_min= node->z_min; - - node->nodes[2]->x_min= x; - node->nodes[2]->y_min= y; - node->nodes[2]->z_min= node->z_min; - - node->nodes[3]->x_min= node->x_min; - node->nodes[3]->y_min= y; - node->nodes[3]->z_min= node->z_min; - - node->nodes[4]->x_min= node->x_min; - node->nodes[4]->y_min= node->y_min; - node->nodes[4]->z_min= z; - - node->nodes[5]->x_min= x; - node->nodes[5]->y_min= node->y_min; - node->nodes[5]->z_min= z; - - node->nodes[6]->x_min= x; - node->nodes[6]->y_min= y; - node->nodes[6]->z_min= z; - - node->nodes[7]->x_min= node->x_min; - node->nodes[7]->y_min= y; - node->nodes[7]->z_min= z; + node->nodes[0]->x_min = node->x_min; + node->nodes[0]->y_min = node->y_min; + node->nodes[0]->z_min = node->z_min; + node->nodes[0]->x = node->nodes[0]->x_min + size_x/2; + node->nodes[0]->y = node->nodes[0]->y_min + size_y/2; + node->nodes[0]->z = node->nodes[0]->z_min + size_z/2; + + node->nodes[1]->x_min = x; + node->nodes[1]->y_min = node->y_min; + node->nodes[1]->z_min = node->z_min; + node->nodes[1]->x = node->nodes[1]->x_min + size_x/2; + node->nodes[1]->y = node->nodes[1]->y_min + size_y/2; + node->nodes[1]->z = node->nodes[1]->z_min + size_z/2; + + node->nodes[2]->x_min = x; + node->nodes[2]->y_min = y; + node->nodes[2]->z_min = node->z_min; + node->nodes[2]->x = node->nodes[2]->x_min + size_x/2; + node->nodes[2]->y = node->nodes[2]->y_min + size_y/2; + node->nodes[2]->z = node->nodes[2]->z_min + size_z/2; + + node->nodes[3]->x_min = node->x_min; + node->nodes[3]->y_min = y; + node->nodes[3]->z_min = node->z_min; + node->nodes[3]->x = node->nodes[3]->x_min + size_x/2; + node->nodes[3]->y = node->nodes[3]->y_min + size_y/2; + node->nodes[3]->z = node->nodes[3]->z_min + size_z/2; + + node->nodes[4]->x_min = node->x_min; + node->nodes[4]->y_min = node->y_min; + node->nodes[4]->z_min = z; + node->nodes[4]->x = node->nodes[4]->x_min + size_x/2; + node->nodes[4]->y = node->nodes[4]->y_min + size_y/2; + node->nodes[4]->z = node->nodes[4]->z_min + size_z/2; + + node->nodes[5]->x_min = x; + node->nodes[5]->y_min = node->y_min; + node->nodes[5]->z_min = z; + node->nodes[5]->x = node->nodes[5]->x_min + size_x/2; + node->nodes[5]->y = node->nodes[5]->y_min + size_y/2; + node->nodes[5]->z = node->nodes[5]->z_min + size_z/2; + + node->nodes[6]->x_min = x; + node->nodes[6]->y_min = y; + node->nodes[6]->z_min = z; + node->nodes[6]->x = node->nodes[6]->x_min + size_x/2; + node->nodes[6]->y = node->nodes[6]->y_min + size_y/2; + node->nodes[6]->z = node->nodes[6]->z_min + size_z/2; + + node->nodes[7]->x_min = node->x_min; + node->nodes[7]->y_min = y; + node->nodes[7]->z_min = z; + node->nodes[7]->x = node->nodes[7]->x_min + size_x/2; + node->nodes[7]->y = node->nodes[7]->y_min + size_y/2; + node->nodes[7]->z = node->nodes[7]->z_min + size_z/2; ml_p= node->elems.first; @@ -1937,7 +1960,7 @@ void subdivide_metaball_octal_node(octal_node *node, float *size, short depth) if(depth>0){ for(a=0;a<8;a++){ if(node->nodes[a]->count > 0) /* if node is not empty, then it is subdivided */ - subdivide_metaball_octal_node(node->nodes[a], size, depth); + subdivide_metaball_octal_node(node->nodes[a], size_x, size_y, size_z, depth); } } } @@ -2009,7 +2032,7 @@ void init_metaball_octal_tree(int depth) size[2]= node->z_max - node->z_min; /* first node is subdivided recursively */ - subdivide_metaball_octal_node(node, size, metaball_tree->depth); + subdivide_metaball_octal_node(node, size[0], size[1], size[2], metaball_tree->depth); } void metaball_polygonize(Object *ob) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2a8ba878c41..83a9bd66b8d 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1248,7 +1248,8 @@ static DerivedMesh *arrayModifier_applyModifier( result = arrayModifier_doArray(amd, ob, derivedData, 0); - CDDM_calc_normals(result); + if(result != derivedData) + CDDM_calc_normals(result); return result; } @@ -2674,7 +2675,8 @@ static DerivedMesh *edgesplitModifier_applyModifier( result = edgesplitModifier_do(emd, ob, derivedData); - CDDM_calc_normals(result); + if(result != derivedData) + CDDM_calc_normals(result); return result; } @@ -5995,20 +5997,29 @@ static void explodeModifier_createFacepa(ExplodeModifierData *emd, if(vertpa) MEM_freeN(vertpa); BLI_kdtree_free(tree); } + +static int edgesplit_get(EdgeHash *edgehash, int v1, int v2) +{ + return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2)); +} + static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){ DerivedMesh *splitdm; MFace *mf=0,*df1=0,*df2=0,*df3=0; MFace *mface=CDDM_get_faces(dm); MVert *dupve, *mv; + EdgeHash *edgehash; + EdgeHashIterator *ehi; int totvert=dm->getNumVerts(dm); int totface=dm->getNumFaces(dm); - int *edgesplit = MEM_callocN(sizeof(int)*totvert*totvert,"explode_edgesplit"); - int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_edgesplit"); + int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit"); int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2"); int *facepa = emd->facepa; int *fs, totesplit=0,totfsplit=0,totin=0,curdupvert=0,curdupface=0,curdupin=0; - int i,j,v1,v2,v3,v4; + int i,j,v1,v2,v3,v4,esplit; + + edgehash= BLI_edgehash_new(); /* recreate vertpa from facepa calculation */ for (i=0,mf=mface; i<totface; i++,mf++) { @@ -6028,22 +6039,22 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive v4=vertpa[mf->v4]; if(v1!=v2){ - edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); (*fs)++; } if(v2!=v3){ - edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1; + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); (*fs)++; } if(v3!=v4){ - edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1; + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); (*fs)++; } if(v1!=v4){ - edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); (*fs)++; } @@ -6052,28 +6063,29 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive *fs=1; else if(v1!=v2){ if(v1!=v4) - edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1; + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); else - edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1; + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); } else{ if(v1!=v4) - edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); else - edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1; + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); } } } } /* count splits & reindex */ + ehi= BLI_edgehashIterator_new(edgehash); totesplit=totvert; - for(j=0; j<totvert; j++){ - for(i=j+1; i<totvert; i++){ - if(edgesplit[j*totvert+i]) - edgesplit[j*totvert+i]=edgesplit[i*totvert+j]=totesplit++; - } + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit)); + totesplit++; } + BLI_edgehashIterator_free(ehi); + /* count new faces due to splitting */ for(i=0,fs=facesplit; i<totface; i++,fs++){ if(*fs==1) @@ -6121,23 +6133,23 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive /* create new verts */ curdupvert=totvert; - for(j=0; j<totvert; j++){ - for(i=j+1; i<totvert; i++){ - if(edgesplit[j*totvert+i]){ - mv=CDDM_get_vert(splitdm,j); - dupve=CDDM_get_vert(splitdm,edgesplit[j*totvert+i]); + ehi= BLI_edgehashIterator_new(edgehash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_getKey(ehi, &i, &j); + esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + mv=CDDM_get_vert(splitdm,j); + dupve=CDDM_get_vert(splitdm,esplit); - DM_copy_vert_data(splitdm,splitdm,j,edgesplit[j*totvert+i],1); + DM_copy_vert_data(splitdm,splitdm,j,esplit,1); - *dupve=*mv; + *dupve=*mv; - mv=CDDM_get_vert(splitdm,i); + mv=CDDM_get_vert(splitdm,i); - VECADD(dupve->co,dupve->co,mv->co); - VecMulf(dupve->co,0.5); - } - } + VECADD(dupve->co,dupve->co,mv->co); + VecMulf(dupve->co,0.5); } + BLI_edgehashIterator_free(ehi); /* create new faces */ curdupface=totface; @@ -6158,14 +6170,14 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v1==v2){ - df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df1->v2=edgesplit[mf->v2*totvert+mf->v3]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); mf->v3=df1->v2; mf->v4=df1->v1; } else{ - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df1->v4=edgesplit[mf->v3*totvert+mf->v4]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); mf->v2=df1->v1; mf->v3=df1->v4; } @@ -6188,8 +6200,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive if(v1!=v2){ if(v1!=v4){ - df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df1->v2=edgesplit[mf->v1*totvert+mf->v2]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); df2->v1=df1->v3=mf->v2; df2->v3=df1->v4=mf->v4; df2->v2=mf->v3; @@ -6202,8 +6214,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[i]=v1; } else{ - df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df1->v3=edgesplit[mf->v2*totvert+mf->v3]; + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); df1->v4=mf->v3; df2->v2=mf->v3; df2->v3=mf->v4; @@ -6219,8 +6231,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } else{ if(v1!=v4){ - df1->v3=edgesplit[mf->v3*totvert+mf->v4]; - df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); df1->v2=mf->v3; mf->v1=df1->v4; @@ -6232,8 +6244,8 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[i]=v4; } else{ - df1->v3=edgesplit[mf->v2*totvert+mf->v3]; - df1->v4=edgesplit[mf->v3*totvert+mf->v4]; + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); df1->v1=mf->v4; df1->v2=mf->v2; df2->v3=mf->v4; @@ -6269,9 +6281,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v1==v2){ - df2->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df3->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df3->v3=df2->v2=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v3; df2->v3=mf->v4; df1->v4=df2->v4=df3->v4=0; @@ -6284,9 +6296,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v4; } else if(v2==v3){ - df3->v1=df2->v3=df1->v1=edgesplit[mf->v1*totvert+mf->v4]; - df2->v2=df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df3->v2=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v3=mf->v4; df2->v1=mf->v1; @@ -6300,9 +6312,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v1; } else if(v3==v4){ - df3->v2=df2->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df2->v3=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df3->v3=df1->v3=edgesplit[mf->v1*totvert+mf->v4]; + df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4); df3->v1=mf->v1; df2->v2=mf->v2; @@ -6316,9 +6328,9 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-2]=v2; } else{ - df3->v1=df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v3=df2->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3]; - df2->v3=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v2; df2->v2=mf->v3; @@ -6369,11 +6381,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive *df3=*mf; curdupface++; - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); - df2->v1=edgesplit[mf->v1*totvert+mf->v4]; - df3->v4=df2->v3=edgesplit[mf->v3*totvert+mf->v4]; + df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v1=df2->v2=df1->v4=curdupin; @@ -6410,11 +6422,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive curdupface++; if(v2==v3){ - df1->v1=edgesplit[mf->v1*totvert+mf->v2]; - df3->v1=df1->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3]; - df2->v1=df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); - df3->v3=df2->v3=edgesplit[mf->v3*totvert+mf->v4]; + df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); df3->v2=mf->v3; df3->v4=0; @@ -6428,11 +6440,11 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive facepa[curdupface-1]=v3; } else{ - df3->v1=df2->v1=df1->v2=edgesplit[mf->v1*totvert+mf->v2]; - df2->v4=df1->v3=edgesplit[mf->v3*totvert+mf->v4]; - df1->v4=edgesplit[mf->v1*totvert+mf->v4]; + df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); - df3->v3=df2->v2=edgesplit[mf->v2*totvert+mf->v3]; + df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3); df3->v4=0; @@ -6456,7 +6468,7 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } } - MEM_freeN(edgesplit); + BLI_edgehash_free(edgehash, NULL); MEM_freeN(facesplit); MEM_freeN(vertpa); @@ -6836,8 +6848,16 @@ static void meshdeformModifier_do( Mat3CpyMat4(icagemat, iobmat); /* bind weights if needed */ - if(!mmd->bindcos) - harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); + if(!mmd->bindcos) { + static int recursive = 0; + + /* progress bar redraw can make this recursive .. */ + if(!recursive) { + recursive = 1; + harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); + recursive = 0; + } + } /* verify we have compatible weights */ totvert= numVerts; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 28c3e1c64e6..4e36df35a14 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1989,7 +1989,7 @@ void ntreeEndExecTree(bNodeTree *ntree) if(ntree->threadstack) { for(a=0; a<BLENDER_MAX_THREADS; a++) { for(nts=ntree->threadstack[a].first; nts; nts=nts->next) - MEM_freeN(nts->stack); + if (nts->stack) MEM_freeN(nts->stack); BLI_freelistN(&ntree->threadstack[a]); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bd8e0da3232..40664cb049a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1056,6 +1056,7 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->effectors.first= psysn->effectors.last= 0; psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL; + psysn->childcachebufs.first = psysn->childcachebufs.last = NULL; psysn->reactevents.first = psysn->reactevents.last = NULL; psysn->renderdata = NULL; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d0152de3091..3e917396d1d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2401,8 +2401,11 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda psys->pathcache= cache; } - if(edit==NULL && psys->soft && psys->softflag & OB_SB_ENABLE) + if(edit==NULL && psys->soft && psys->softflag & OB_SB_ENABLE) { soft = psys->soft; + if(!soft->bpoint) + soft= NULL; + } psys->lattice = psys_get_lattice(ob, psys); ma= give_current_material(ob, psys->part->omat); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 596c381b896..5112fb08fe6 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3770,10 +3770,12 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS near=0; for(n=1; n<neighbours; n++){ if(ptn[n].dist<2.0f*pa->size){ - bvf->Subf(dvec,pa->state.co,pars[ptn[n].index].state.co); - bvf->Mulf(dvec,(2.0f*pa->size-ptn[n].dist)/ptn[n].dist); - bvf->Addf(avoid,avoid,dvec); - near++; + if(ptn[n].dist!=0.0f) { + bvf->Subf(dvec,pa->state.co,pars[ptn[n].index].state.co); + bvf->Mulf(dvec,(2.0f*pa->size-ptn[n].dist)/ptn[n].dist); + bvf->Addf(avoid,avoid,dvec); + near++; + } } /* ptn[] is distance ordered so no need to check others */ else break; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 6798c3c47b7..2898dca767c 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -67,6 +67,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_ipo.h" +#include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" @@ -149,6 +150,11 @@ void free_scene(Scene *sce) MEM_freeN(sce->r.qtcodecdata); sce->r.qtcodecdata = NULL; } + if (sce->r.ffcodecdata.properties) { + IDP_FreeProperty(sce->r.ffcodecdata.properties); + MEM_freeN(sce->r.ffcodecdata.properties); + sce->r.ffcodecdata.properties = NULL; + } BLI_freelistN(&sce->markers); BLI_freelistN(&sce->transform_spaces); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 768f5ff980e..9005db1312f 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3390,8 +3390,9 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo int a; /* update the vertex locations */ - if(sb->particles) { + if(sb->particles && sb->particles->totpart>0) { psmd= psys_get_modifier(ob,sb->particles); + pa= sb->particles->particles; key= pa->hair; @@ -3434,7 +3435,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int float hairmat[4][4]; int a; - if(sb->particles) { + if(sb->particles && sb->particles->totpart>0) { psmd= psys_get_modifier(ob, sb->particles); pa= sb->particles->particles; key= pa->hair; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index e79e36a1498..c95e3d20442 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -33,6 +33,7 @@ #include <ffmpeg/avcodec.h> #include <ffmpeg/rational.h> #include <ffmpeg/swscale.h> +#include <ffmpeg/opt.h> #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 @@ -58,6 +59,7 @@ #include "BKE_bad_level_calls.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -224,6 +226,10 @@ static const char** get_file_extensions(int format) static const char * rv[] = { ".flv", NULL }; return rv; } + case FFMPEG_MKV: { + static const char * rv[] = { ".mkv", NULL }; + return rv; + } default: return NULL; } @@ -337,6 +343,75 @@ static AVFrame* generate_video_frame(uint8_t* pixels) return current_frame; } +static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop) +{ + char name[128]; + char * param; + const AVOption * rv = NULL; + + fprintf(stderr, "FFMPEG expert option: %s: ", prop->name); + + strncpy(name, prop->name, 128); + + param = strchr(name, ':'); + + if (param) { + *param++ = 0; + } + + switch(prop->type) { + case IDP_STRING: + fprintf(stderr, "%s.\n", IDP_String(prop)); + rv = av_set_string(c, prop->name, IDP_String(prop)); + break; + case IDP_FLOAT: + fprintf(stderr, "%g.\n", IDP_Float(prop)); + rv = av_set_double(c, prop->name, IDP_Float(prop)); + break; + case IDP_INT: + fprintf(stderr, "%d.\n", IDP_Int(prop)); + + if (param) { + if (IDP_Int(prop)) { + rv = av_set_string(c, name, param); + } else { + return; + } + } else { + rv = av_set_int(c, prop->name, IDP_Int(prop)); + } + break; + } + + if (!rv) { + fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n", + prop->name); + } +} + +static void set_ffmpeg_properties(AVCodecContext* c, const char * prop_name) +{ + IDProperty * prop; + void * iter; + IDProperty * curr; + + if (!G.scene->r.ffcodecdata.properties) { + return; + } + + prop = IDP_GetPropertyFromGroup( + G.scene->r.ffcodecdata.properties, (char*) prop_name); + if (!prop) { + return; + } + + iter = IDP_GetGroupIterator(prop); + + while ((curr = IDP_GroupIterNext(iter)) != NULL) { + set_ffmpeg_property_option(c, curr); + } +} + /* prepare a video stream for the output file */ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, @@ -423,13 +498,18 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, } /* Determine whether we are encoding interlaced material or not */ - if (G.scene->r.mode & (1 << 6)) { + if (G.scene->r.mode & R_FIELDS) { fprintf(stderr, "Encoding interlaced video\n"); c->flags |= CODEC_FLAG_INTERLACED_DCT; c->flags |= CODEC_FLAG_INTERLACED_ME; - } - c->sample_aspect_ratio.num = G.scene->r.xasp; - c->sample_aspect_ratio.den = G.scene->r.yasp; + } + + /* xasp & yasp got float lately... */ + + c->sample_aspect_ratio = av_d2q( + ((double) G.scene->r.xasp / (double) G.scene->r.yasp), 255); + + set_ffmpeg_properties(c, "video"); if (avcodec_open(c, codec) < 0) { error("Couldn't initialize codec"); @@ -474,6 +554,9 @@ static AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) error("Couldn't find a valid audio codec"); return NULL; } + + set_ffmpeg_properties(c, "audio"); + if (avcodec_open(c, codec) < 0) { error("Couldn't initialize audio codec"); return NULL; diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h index f3aa69d77ff..abbd17c3635 100644 --- a/source/blender/blenlib/BLI_edgehash.h +++ b/source/blender/blenlib/BLI_edgehash.h @@ -86,6 +86,9 @@ void BLI_edgehashIterator_getKey (EdgeHashIterator *ehi, int *v0_r, int *v1 /* Retrieve the value from an iterator. */ void* BLI_edgehashIterator_getValue (EdgeHashIterator *ehi); + /* Set the value for an iterator. */ +void BLI_edgehashIterator_setValue (EdgeHashIterator *ehi, void *val); + /* Steps the iterator to the next index. */ void BLI_edgehashIterator_step (EdgeHashIterator *ehi); diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index 21810613c7f..acd53e5d516 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -130,7 +130,7 @@ static int vertex_sort(const void *p1, const void *p2) * 'box->index' is not used at all, the only reason its there * is that the box array is sorted by area and programs need to be able * to have some way of writing the boxes back to the original data. - * len - the number of boxes in teh array. + * len - the number of boxes in the array. * tot_width and tot_height are set so you can normalize the data. * */ void boxPack2D(boxPack *boxarray, int len, float *tot_width, float *tot_height) diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index 6aa0ded63b9..3e1c8afb7a8 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -200,6 +200,11 @@ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) { return ehi->curEntry?ehi->curEntry->val:NULL; } +void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) { + if(ehi->curEntry) + ehi->curEntry->val= val; +} + void BLI_edgehashIterator_step(EdgeHashIterator *ehi) { if (ehi->curEntry) { ehi->curEntry= ehi->curEntry->next; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e69b2fb0326..25f225c5bbe 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3601,7 +3601,16 @@ static void direct_link_scene(FileData *fd, Scene *sce) if (sce->r.qtcodecdata) { sce->r.qtcodecdata->cdParms = newdataadr(fd, sce->r.qtcodecdata->cdParms); } - + if (sce->r.ffcodecdata.properties) { + sce->r.ffcodecdata.properties = newdataadr( + fd, sce->r.ffcodecdata.properties); + if (sce->r.ffcodecdata.properties) { + IDP_DirectLinkProperty( + sce->r.ffcodecdata.properties, + (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } + } + link_list(fd, &(sce->markers)); link_list(fd, &(sce->transform_spaces)); link_list(fd, &(sce->r.layers)); @@ -7377,6 +7386,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* needed for proper libdata lookup */ oldnewmap_insert(fd->libmap, psys->part, psys->part, 0); + part->id.lib= ob->id.lib; part->id.us--; part->id.flag |= (ob->id.flag & LIB_NEEDLINK); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 47ccd333dd9..b4a9f225470 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1532,6 +1532,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, "QuicktimeCodecData", 1, sce->r.qtcodecdata); if (sce->r.qtcodecdata->cdParms) writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); } + if (sce->r.ffcodecdata.properties) { + IDP_WriteProperty(sce->r.ffcodecdata.properties, wd); + } /* writing dynamic list of TimeMarkers to the blend file */ for(marker= sce->markers.first; marker; marker= marker->next) diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 86f84c1e028..ca9f3d6a378 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -260,5 +260,6 @@ int EM_vertColorCheck(void); /* can we edit colors for this mesh?*/ void EM_set_actFace(struct EditFace *efa); struct EditFace * EM_get_actFace(int sloppy); +int EM_get_actSelection(struct EditSelection *ese); #endif diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index be1f5581be7..83031ff3bad 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -59,7 +59,7 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] void draw_depth(struct ScrArea *sa, void *spacedata); void view3d_update_depths(struct View3D *v3d); -int update_time(void); +int update_time(int cfra); void calc_viewborder(struct View3D *v3d, struct rctf *viewborder_r); void view3d_set_1_to_1_viewborder(struct View3D *v3d); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 242965a820c..7571d64be91 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -359,6 +359,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_SET_ZBLUR 1644 #define B_ADD_RENDERLAYER 1645 #define B_SET_PASS 1646 +#define B_ADD_FFMPEG_VIDEO_OPTION 1647 +#define B_ADD_FFMPEG_AUDIO_OPTION 1648 #define B_SEQ_BUT_PLUGIN 1691 #define B_SEQ_BUT_RELOAD 1692 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index de89c0e51cb..83168248b9a 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -59,6 +59,27 @@ typedef struct bDeformGroup { char name[32]; } bDeformGroup; +/** + * The following illustrates the orientation of the + * bounding box in local space + * + * + * Z Y + * | / + * |/ + * .-----X + * + * + * 2----------6 + * /| /| + * / | / | + * 1----------5 | + * | | | | + * | 3-------|--7 + * | / | / + * |/ |/ + * 0----------4 + */ typedef struct BoundBox { float vec[8][3]; int flag, pad; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3d1641a2110..58f7f55ef74 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -98,6 +98,7 @@ typedef struct FFMpegCodecData { int rc_buffer_size; int mux_packet_size; int mux_rate; + IDProperty *properties; } FFMpegCodecData; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 86f6e4bcbe4..619dfbb43a0 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -524,7 +524,8 @@ typedef struct SpaceImaSel { #define SI_DRAW_STRETCH 1<<21 /* SpaceIpo->flag */ -#define SIPO_LOCK_VIEW 1<<0 +#define SIPO_LOCK_VIEW 1<<0 +#define SIPO_NOTRANSKEYCULL 1<<1 /* SpaceText flags (moved from DNA_text_types.h) */ @@ -616,6 +617,7 @@ typedef struct SpaceImaSel { #define SNLA_ALLKEYED 1 #define SNLA_ACTIVELAYERS 2 #define SNLA_DRAWTIME 4 +#define SNLA_NOTRANSKEYCULL 8 /* time->flag */ /* show timing in frames instead of in seconds */ diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript index 574e289d3a9..872fd515f1d 100644 --- a/source/blender/makesdna/intern/SConscript +++ b/source/blender/makesdna/intern/SConscript @@ -25,7 +25,6 @@ if sys.platform != 'cygwin': makesdna_tool.Append (CCFLAGS = cflags) makesdna_tool.Append (CPPDEFINES = defines) makesdna_tool.Append (LIBPATH = '#'+root_build_dir+'/lib') -makesdna_tool.Append (LINKFLAGS = env['PLATFORM_LINKFLAGS']) if env['BF_PROFILE']: makesdna_tool.Append (LINKFLAGS = env['BF_PROFILE_FLAGS']) diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c index 6cd1c5981a6..ff9e2b716ce 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_gamma.c @@ -46,7 +46,8 @@ static void do_gamma(bNode *node, float *out, float *in, float *fac) { int i=0; for(i=0; i<3; i++) { - out[i] = pow(in[i],fac[0]); + /* check for negative to avoid nan's */ + out[i] = (in[0] > 0.0f)? pow(in[i],fac[0]): in[0]; } out[3] = in[3]; } diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c index 78f780c43b1..49473b213ce 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c @@ -239,6 +239,27 @@ static void node_dynamic_reset(bNode *node, int unlink_text) tinfo = node->typeinfo; tinfo_default = node_dynamic_find_typeinfo(&node_all_shaders, NULL); + if ((tinfo == tinfo_default) && unlink_text) { + ID *textID = node->id; + /* already at default (empty) state, which happens if this node's + * script failed to parse at the first stage: definition. We're here + * because its text was removed from Blender. */ + for (ma= G.main->mat.first; ma; ma= ma->id.next) { + if (ma->nodetree) { + bNode *nd; + for (nd= ma->nodetree->nodes.first; nd; nd = nd->next) { + if (nd->id == textID) { + nd->id = NULL; + nd->custom1 = 0; + nd->custom1 = BSET(nd->custom1, NODE_DYNAMIC_NEW); + BLI_strncpy(nd->name, "Dynamic", 8); + return; + } + } + } + } + } + node_dynamic_rem_all_links(tinfo); node_dynamic_free_typeinfo_sockets(tinfo); diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index cd7ec781b2b..3d4546613be 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -2063,22 +2063,22 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) /*GLfloat scissorBox[4];*/ /* parse the arguments passed-in from Python */ - if( !PyArg_ParseTuple( args, "Off|ffiiii", &pyObjImage, + if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, &originX, &originY, &zoomX, &zoomY, &clipX, &clipY, &clipW, &clipH ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a Blender.Image and 2 floats, and " \ "optionally 2 floats and 4 ints as arguments" ); - /* check that the first PyObject is actually a Blender.Image */ - if( !BPy_Image_Check( pyObjImage ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a Blender.Image and 2 floats, and " \ - "optionally 2 floats and 4 ints as arguments" ); /* check that the zoom factors are valid */ - if( ( zoomX <= 0.0 ) || ( zoomY <= 0.0 ) ) + if( ( zoomX < 0.0 ) || ( zoomY < 0.0 ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, - "invalid zoom factors - they must be >= 0.0" ); - + "invalid zoom factors - they must be > 0.0" ); + if ((zoomX == 0.0 ) || ( zoomY == 0.0 )) { + /* sometimes python doubles can be converted from small values to a zero float, in this case just dont draw */ + Py_RETURN_NONE; + } + + /* fetch a C Image pointer from the passed-in Python object */ py_img = ( BPy_Image * ) pyObjImage; image = py_img->image; @@ -2101,9 +2101,9 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) * the image as they can. */ clipX = EXPP_ClampInt( clipX, 0, ibuf->x ); clipY = EXPP_ClampInt( clipY, 0, ibuf->y ); - if( ( clipW < 0 ) || ( clipW > ( ibuf->x - clipW ) ) ) + if( ( clipW < 0 ) || ( clipX+clipW > ibuf->x ) ) clipW = ibuf->x - clipX; - if( ( clipH < 0 ) || ( clipH > ( ibuf->y - clipH ) ) ) + if( ( clipH < 0 ) || ( clipY+clipH > ibuf->y ) ) clipH = ibuf->y - clipY; /* -- we are "Go" to Draw! -- */ @@ -2165,8 +2165,7 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); - Py_INCREF( Py_None ); - return Py_None; + Py_RETURN_NONE; } diff --git a/source/blender/python/api2_2x/NLA.c b/source/blender/python/api2_2x/NLA.c index 728d31398a9..cc477c7b5cf 100644 --- a/source/blender/python/api2_2x/NLA.c +++ b/source/blender/python/api2_2x/NLA.c @@ -803,7 +803,7 @@ static int ActionStrip_setBlendMode( BPy_ActionStrip * self, PyObject * value ) #define ACTIONSTRIP_MASK (ACTSTRIP_SELECT | ACTSTRIP_USESTRIDE \ | ACTSTRIP_HOLDLASTFRAME | ACTSTRIP_ACTIVE | ACTSTRIP_LOCK_ACTION \ - | ACTSTRIP_MUTE) + | ACTSTRIP_MUTE | ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ | ACTSTRIP_AUTO_BLENDS) static PyObject *ActionStrip_getFlag( BPy_ActionStrip * self ) { @@ -1169,18 +1169,16 @@ static PyObject *M_ActionStrip_FlagsDict( void ) if( S ) { BPy_constant *d = ( BPy_constant * ) S; - PyConstant_Insert( d, "SELECT", - PyInt_FromLong( ACTSTRIP_SELECT ) ); - PyConstant_Insert( d, "STRIDE_PATH", - PyInt_FromLong( ACTSTRIP_USESTRIDE ) ); - PyConstant_Insert( d, "HOLD", - PyInt_FromLong( ACTSTRIP_HOLDLASTFRAME ) ); - PyConstant_Insert( d, "ACTIVE", - PyInt_FromLong( ACTSTRIP_ACTIVE ) ); - PyConstant_Insert( d, "LOCK_ACTION", - PyInt_FromLong( ACTSTRIP_LOCK_ACTION ) ); - PyConstant_Insert( d, "MUTE", - PyInt_FromLong( ACTSTRIP_MUTE ) ); + PyConstant_Insert( d, "SELECT", PyInt_FromLong( ACTSTRIP_SELECT ) ); + PyConstant_Insert( d, "STRIDE_PATH", PyInt_FromLong( ACTSTRIP_USESTRIDE ) ); + PyConstant_Insert( d, "HOLD", PyInt_FromLong( ACTSTRIP_HOLDLASTFRAME ) ); + PyConstant_Insert( d, "ACTIVE", PyInt_FromLong( ACTSTRIP_ACTIVE ) ); + PyConstant_Insert( d, "LOCK_ACTION", PyInt_FromLong( ACTSTRIP_LOCK_ACTION ) ); + PyConstant_Insert( d, "MUTE", PyInt_FromLong( ACTSTRIP_MUTE ) ); + PyConstant_Insert( d, "USEX", PyInt_FromLong( ACTSTRIP_CYCLIC_USEX ) ); + PyConstant_Insert( d, "USEY", PyInt_FromLong( ACTSTRIP_CYCLIC_USEY ) ); + PyConstant_Insert( d, "USEZ", PyInt_FromLong( ACTSTRIP_CYCLIC_USEZ ) ); + PyConstant_Insert( d, "AUTO_BLEND", PyInt_FromLong( ACTSTRIP_AUTO_BLENDS ) ); } return S; } diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c index 1d420c5e4cb..ad08f07c621 100644 --- a/source/blender/python/api2_2x/Node.c +++ b/source/blender/python/api2_2x/Node.c @@ -919,6 +919,8 @@ static int sockoutmap_set_attr(bNodeStack **stack, short type, short idx, PyObje int i; short len, wanted_len; + if (!stack || !stack[idx]) return 0; /* no MaterialNode */ + if (type == SOCK_VALUE) { val = PyNumber_Float(value); if (!val) diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index 061084da622..fe789fb4811 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -1240,6 +1240,7 @@ static PyObject *M_Window_QHandle( PyObject * self, PyObject * args ) static PyObject *M_Window_TestBreak( PyObject * self ) { if (blender_test_break()) { + G.afbreek= 0; Py_RETURN_TRUE; } else { Py_RETURN_FALSE; diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py index ec1d42bce43..2960d8ed1d2 100644 --- a/source/blender/python/api2_2x/doc/API_intro.py +++ b/source/blender/python/api2_2x/doc/API_intro.py @@ -4,9 +4,7 @@ The Blender Python API Reference ================================ - An asterisk (*) means the module has been updated. - - for a full list of changes since 2.42 see U{http://mediawiki.blender.org/index.php/Release_Notes/Notes243/Python_API} + for a full list of changes since 2.45 see U{http://wiki.blender.org/index.php/Release_Notes/Notes246/Python_API} Top Module: ----------- @@ -16,61 +14,53 @@ The Blender Python API Reference Submodules: ----------- - - L{Armature} (*) + - L{Armature} - L{NLA} - L{Action<NLA.Action>} - - L{BezTriple} (*) + - L{BezTriple} - L{BGL} - - L{Camera} (*) - - L{Curve} (*) - - L{Draw} (*) + - L{Camera} + - L{Curve} + - L{Draw} - L{Effect} - - L{Geometry} (*) - - L{Group} (*) - - L{Image} (*) - - L{Ipo} (*) - - L{IpoCurve} (*) - - L{Key} (*) + - L{Geometry} + - L{Group} + - L{Image} + - L{Ipo} + - L{IpoCurve} + - L{Key} - L{Lamp} - - L{Lattice} (*) - - L{Library} (*) - - L{Material} (*) - - L{Mathutils} (*) - - L{Mesh} (*) - - L{MeshPrimitives} (*) - - L{Metaball} (*) + - L{Lattice} + - L{Library} + - L{Material} + - L{Mathutils} + - L{Mesh} + - L{MeshPrimitives} + - L{Metaball} - L{NMesh} (deprecated) - L{Noise} - - L{Object} (*) - - L{Modifier} (*) - - L{Pose} (*) - - L{Constraint} (*) - - L{ActionStrips<NLA>} (*) + - L{Object} + - L{Modifier} + - L{Pose} + - L{Constraint} + - L{ActionStrips<NLA>} - L{Particle} - L{Registry} - - L{Scene} (*) + - L{Scene} - L{Radio} - - L{Render} (*) - - L{Sound} (*) + - L{Render} + - L{Sound} - L{Text} - L{Text3d} - L{Font} - - L{Texture} (*) + - L{Texture} - L{TimeLine} - L{Types} - L{Window} - - L{Theme} (*) + - L{Theme} - L{World} - L{sys<Sys>} - Additional information: - ----------------------- - - - L{Special features<API_related>}: - - scripts: registering in menus, documenting, configuring (new); - - command line examples (new); - - script links (*), space handler script links, Group module (new). - Introduction: ============= @@ -226,9 +216,8 @@ A note to newbie script writers: to get an idea of what can be done, you may be surprised. @author: The Blender Python Team -@requires: Blender 2.43 or newer. -@version: 2.43 -@see: U{www.blender3d.org<http://www.blender3d.org>}: main site +@requires: Blender 2.46 or newer. +@version: 2.46 @see: U{www.blender.org<http://www.blender.org>}: documentation and forum @see: U{blenderartists.org<http://blenderartists.org>}: user forum @see: U{projects.blender.org<http://projects.blender.org>} @@ -238,9 +227,9 @@ A note to newbie script writers: @see: U{Blending into Python<en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python>}: User contributed documentation, featuring a blender/python cookbook with many examples. @note: the official version of this reference guide is only updated for each - new Blender release. But you can build the current CVS + new Blender release. But you can build the current SVN version yourself: install epydoc, grab all files in the - source/blender/python/api2_2x/doc/ folder of Blender's CVS and use the + source/blender/python/api2_2x/doc/ folder of Blender's SVN and use the epy_docgen.sh script also found there to generate the html docs. Naturally you will also need a recent Blender binary to try the new features. If you prefer not to compile it yourself, there is a testing diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py index 40bf9001a76..964b8f70e8b 100644 --- a/source/blender/python/api2_2x/doc/Blender.py +++ b/source/blender/python/api2_2x/doc/Blender.py @@ -116,6 +116,14 @@ def Get (request): @return: The requested data or None if not found. """ +def GetPaths (absolute=0): + """ + Returns a list of files this blend file uses: (libraries, images, sounds, fonts, sequencer movies). + @type absolute: bool + @param absolute: When true, the absolute paths of every file will be returned. + @return: A list for paths (strings) that this blend file uses. + """ + def Redraw (): """ Redraw all 3D windows. @@ -245,4 +253,4 @@ def SaveUndoState (message): Sets an undo at the current state. @param message: Message that appiers in the undo menu @type message: string - """
\ No newline at end of file + """ diff --git a/source/blender/python/api2_2x/doc/Image.py b/source/blender/python/api2_2x/doc/Image.py index 92a05c2604d..564cac3ef9b 100644 --- a/source/blender/python/api2_2x/doc/Image.py +++ b/source/blender/python/api2_2x/doc/Image.py @@ -48,7 +48,7 @@ def New (name, width, height, depth): @type height: int @param height: The height of the new Image object, between 1 and 5000. @type depth: int - @param depth: The colour depth of the new Image object. (32:RGBA 8bit channels, 128:RGBA 32bit high dynamic range float channels). + @param depth: The color depth of the new Image object. (32:RGBA 8bit channels, 128:RGBA 32bit high dynamic range float channels). @rtype: Blender Image @return: A new Blender Image object. """ diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index d8bd7be6566..4a53f869283 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -667,6 +667,8 @@ class MFaceSeq: True, the method will return a list representing the new index for each face in the input list. If faces are removed as duplicates, None is inserted in place of the index. + @type smooth: boolean + @param smooth: keyword parameter (default is False). If supplied new faces will have smooth enabled. @warning: Faces using the first vertex at the 3rd or 4th location in the face's vertex list will have their order rotated so that the zero index on in the first or second location in the face. When creating face data diff --git a/source/blender/python/api2_2x/doc/NLA.py b/source/blender/python/api2_2x/doc/NLA.py index aeb5178f3d7..0e30bfb118f 100644 --- a/source/blender/python/api2_2x/doc/NLA.py +++ b/source/blender/python/api2_2x/doc/NLA.py @@ -19,7 +19,11 @@ It is a bitmask and settings are ORed together. - ACTIVE: action strip is active in NLA window - LOCK_ACTION: action start/end are automatically mapped to strip duration - MUTE: action strip does not contribute to the NLA solution - + - USEX: Turn off automatic single-axis cycling and use X as an offset axis. Note that you can use multiple axes at once. + - USEY: Turn off automatic single-axis cycling and use Y as an offset axis. Note that you can use multiple axes at once. + - USEZ: Turn off automatic single-axis cycling and use Z as an offset axis. Note that you can use multiple axes at once. + - AUTO_BLEND: Automatic calculation of blend in/out values + @type StrideAxes: readonly dictionary @var StrideAxes: Constant dict used by the L{ActionStrip.strideAxis} attribute. Values are STRIDEAXIS_X, STRIDEAXIS_Y, and STRIDEAXIS_Z. diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py index cf886ad27f1..475a4fc5b10 100644 --- a/source/blender/python/api2_2x/doc/Render.py +++ b/source/blender/python/api2_2x/doc/Render.py @@ -399,6 +399,16 @@ class RenderData: @type bakeDist: float @ivar bakeBias: The distance in blender units to bias faces further away from the object. @type bakeBias: float + @ivar halfFloat: When enabled use 16bit floats rather then 32bit for OpenEXR files. + @type halfFloat: bool + @ivar zbuf: When enabled, save the zbuffer with an OpenEXR file + @type zbuf: bool + @ivar preview: When enabled, save a preview jpeg with an OpenEXR file + @type preview: bool + @ivar touch: Create an empty file before rendering it. + @type touch: bool + @ivar noOverwrite: Skip rendering frames when the file exists. + @type noOverwrite: bool """ def currentFrame(frame = None): diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index 5161ac5ea56..7f42d06240b 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -80,7 +80,7 @@ Example:: @type ExtendModes: readonly dictionary @var ExtendModes: Extend, clip, repeat or checker modes for image textures - - EXTEND - Extends the colour of the edge + - EXTEND - Extends the color of the edge - CLIP - Return alpha 0.0 outside image - CLIPCUBE - Return alpha 0.0 around cube-shaped area around image - REPEAT - Repeat image vertically and horizontally @@ -209,10 +209,10 @@ Example:: @type TexCo: readonly dictionary @var MapTo: Flags for MTex.mapto. - - COL - Make the texture affect the basic colour of the material + - COL - Make the texture affect the basic color of the material - NOR - Make the texture affect the rendered normal - - CSP - Make the texture affect the specularity colour - - CMIR - Make the texture affect the mirror colour + - CSP - Make the texture affect the specularity color + - CMIR - Make the texture affect the mirror color - REF - Make the texture affect the diffuse reflectivity value - SPEC - Make the texture affect the specularity value - HARD - Make the texture affect the hardness value diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index fdc65608146..44cc8f56a1a 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -2007,19 +2007,19 @@ static int RenderData_setIValueAttrClamp( BPy_RenderData *self, PyObject *value, case EXPP_RENDER_ATTR_CFRAME: min = 1; max = MAXFRAME; - size = 'h'; + size = 'i'; param = &self->renderContext->cfra; break; case EXPP_RENDER_ATTR_EFRAME: min = 1; max = MAXFRAME; - size = 'h'; + size = 'i'; param = &self->renderContext->efra; break; case EXPP_RENDER_ATTR_SFRAME: min = 1; max = MAXFRAME; - size = 'h'; + size = 'i'; param = &self->renderContext->sfra; break; case EXPP_RENDER_ATTR_FPS: diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index d8f6836005b..66dc1dd5fef 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -177,6 +177,9 @@ void RE_DataBase_ApplyWindow(struct Render *re); /* override the scene setting for amount threads, commandline */ void RE_set_max_threads(int threads); +/* set the render threads based on the commandline and autothreads setting */ +void RE_init_threadcount(Render *re); + /* the main processor, assumes all was set OK! */ void RE_TileProcessor(struct Render *re, int firsttile, int threaded); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index c2d2ea96745..d7e71b3e531 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -265,7 +265,7 @@ typedef struct ObjectRen { char (*mtface)[32]; char (*mcol)[32]; - int actmtface, actmcol; + int actmtface, actmcol, bakemtface; float obmat[4][4]; /* only used in convertblender.c, for instancing */ } ObjectRen; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 33cad2789c6..dbade68ba1d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -5417,6 +5417,9 @@ void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) /* renderdata setup and exceptions */ re->r= scene->r; + + RE_init_threadcount(re); + re->flag |= R_GLOB_NOPUNOFLIP; re->excludeob= actob; if(type == RE_BAKE_LIGHT) diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 12d0efa59e8..73db5c4b0be 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -225,7 +225,7 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) ObjectInstanceRen *obi; LampRen *lar = NULL; HaloRen *har = NULL; - float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3]; + float imat[3][3], pmat[4][4], smat[4][4], tmat[4][4], cmat[3][3], tmpmat[4][4]; int a; if(mode==0) { @@ -239,8 +239,10 @@ static void env_rotate_scene(Render *re, float mat[][4], int mode) for(obi=re->instancetable.first; obi; obi=obi->next) { /* append or set matrix depending on dupli */ - if(obi->flag & R_DUPLI_TRANSFORMED) - Mat4MulMat4(obi->mat, tmat, obi->mat); + if(obi->flag & R_DUPLI_TRANSFORMED) { + Mat4CpyMat4(tmpmat, obi->mat); + Mat4MulMat4(obi->mat, tmat, tmpmat); + } else if(mode==1) Mat4CpyMat4(obi->mat, tmat); else diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index ba971d28524..e9035f29b3c 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -459,7 +459,14 @@ void RE_SetCamera(Render *re, Object *camera) if(cam->type==CAM_ORTHO) re->r.mode |= R_ORTHO; - /* updating these values from ipo's/drivers is handeled by the depgraph */ + /* solve this too... all time depending stuff is in convertblender.c? + * Need to update the camera early because it's used for projection matrices + * and other stuff BEFORE the animation update loop is done + * */ + if(cam->ipo) { + calc_ipo(cam->ipo, frame_to_float(re->r.cfra)); + execute_ipo(&cam->id, cam->ipo); + } lens= cam->lens; shiftx=cam->shiftx; shifty=cam->shifty; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index feccec6461f..27abbf96122 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1121,11 +1121,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, int winx, int winy /* we clip faces with a minimum of 2 pixel boundary outside of image border. see zbuf.c */ re->clipcrop= 1.0f + 2.0f/(float)(re->winx>re->winy?re->winy:re->winx); - if ((rd->mode & R_FIXED_THREADS)==0 || commandline_threads == 0) { /* Automatic threads */ - re->r.threads = BLI_system_thread_count(); - } else if(commandline_threads >= 1 && commandline_threads<=BLENDER_MAX_THREADS) { - re->r.threads= commandline_threads; - } + RE_init_threadcount(re); } } @@ -2688,3 +2684,12 @@ void RE_set_max_threads(int threads) printf("Error, threads has to be in range 1-%d\n", BLENDER_MAX_THREADS); } } + +void RE_init_threadcount(Render *re) +{ + if ((re->r.mode & R_FIXED_THREADS)==0 || commandline_threads == 0) { /* Automatic threads */ + re->r.threads = BLI_system_thread_count(); + } else if(commandline_threads >= 1 && commandline_threads<=BLENDER_MAX_THREADS) { + re->r.threads= commandline_threads; + } +} diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 7ffed72329e..6c7e69d29ac 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -384,7 +384,7 @@ static float shade_by_transmission(Isect *is, ShadeInput *shi, ShadeResult *shr) static void ray_fadeout_endcolor(float *col, ShadeInput *origshi, ShadeInput *shi, ShadeResult *shr, Isect *isec, float *vec) { - /* un-intersected rays get either rendered material colour or sky colour */ + /* un-intersected rays get either rendered material color or sky color */ if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOMAT) { VECCOPY(col, shr->combined); } else if (origshi->mat->fadeto_mir == MA_RAYMIR_FADETOSKY) { @@ -397,7 +397,7 @@ static void ray_fadeout_endcolor(float *col, ShadeInput *origshi, ShadeInput *sh static void ray_fadeout(Isect *is, ShadeInput *shi, float *col, float *blendcol, float dist_mir) { - /* if fading out, linear blend against fade colour */ + /* if fading out, linear blend against fade color */ float blendfac; blendfac = 1.0 - VecLenf(shi->co, is->start)/dist_mir; @@ -544,8 +544,8 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, flo if (dist_mir > 0.0) { float blendcol[3]; - /* max ray distance set, but found an intersection, so fade this colour - * out towards the sky/material colour for a smooth transition */ + /* max ray distance set, but found an intersection, so fade this color + * out towards the sky/material color for a smooth transition */ ray_fadeout_endcolor(blendcol, origshi, &shi, origshr, &isec, vec); ray_fadeout(&isec, &shi, col, blendcol, dist_mir); } diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 8956359b784..9ff1bfd4e76 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2293,7 +2293,7 @@ static int get_next_bake_face(BakeShade *bs) vlr= RE_findOrAddVlak(obr, v); if((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { - tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); + tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); if(tface && tface->tpage) { Image *ima= tface->tpage; @@ -2347,7 +2347,7 @@ static void shade_tface(BakeShade *bs) VlakRen *vlr= bs->vlr; ObjectInstanceRen *obi= bs->obi; ObjectRen *obr= obi->obr; - MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0); + MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); Image *ima= tface->tpage; float vec[4][2]; int a, i1, i2, i3; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 441aa9336be..98b1426e8ff 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -501,6 +501,7 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) if (layer->type == CD_MTFACE) { strcpy(obr->mtface[mtfn++], layer->name); obr->actmtface= layer->active_rnd; + obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { strcpy(obr->mcol[mcn++], layer->name); diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index bf2ee3dbdd9..7397d623264 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -434,6 +434,8 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert shi->totuv= 0; shi->totcol= 0; + shi->actuv= obr->actmtface; + shi->actcol= obr->actmcol; if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) { for (i=0; (mcol=RE_strandren_get_mcol(obr, strand, i, &name, 0)); i++) { @@ -449,9 +451,9 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } if(shi->totcol) { - shi->vcol[0]= shi->col[0].col[0]; - shi->vcol[1]= shi->col[0].col[1]; - shi->vcol[2]= shi->col[0].col[2]; + shi->vcol[0]= shi->col[shi->actcol].col[0]; + shi->vcol[1]= shi->col[shi->actcol].col[1]; + shi->vcol[2]= shi->col[shi->actcol].col[2]; } else { shi->vcol[0]= 0.0f; @@ -484,7 +486,7 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert suv->dyuv[1]= 0.0f; } - if((mode & MA_FACETEXTURE) && i==0) { + if((mode & MA_FACETEXTURE) && i==obr->actmtface) { if((mode & (MA_VERTEXCOL|MA_VERTEXCOLP))==0) { shi->vcol[0]= 1.0f; shi->vcol[1]= 1.0f; @@ -995,9 +997,9 @@ void shade_input_set_shade_texco(ShadeInput *shi) } if(shi->totcol) { - shi->vcol[0]= shi->col[0].col[0]; - shi->vcol[1]= shi->col[0].col[1]; - shi->vcol[2]= shi->col[0].col[2]; + shi->vcol[0]= shi->col[shi->actcol].col[0]; + shi->vcol[1]= shi->col[shi->actcol].col[1]; + shi->vcol[2]= shi->col[shi->actcol].col[2]; shi->vcol[3]= 1.0f; } else { diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 0a72f976825..27628d91465 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1844,24 +1844,24 @@ void do_material_tex(ShadeInput *shi) } } else { + float nor[3], dot; + if(shi->mat->mode & MA_TANGENT_V) { shi->tang[0]+= Tnor*tex->norfac*texres.nor[0]; shi->tang[1]+= Tnor*tex->norfac*texres.nor[1]; shi->tang[2]+= Tnor*tex->norfac*texres.nor[2]; } - else { - float nor[3], dot; - /* prevent bump to become negative normal */ - nor[0]= Tnor*tex->norfac*texres.nor[0]; - nor[1]= Tnor*tex->norfac*texres.nor[1]; - nor[2]= Tnor*tex->norfac*texres.nor[2]; - - dot= 0.5f + 0.5f*INPR(nor, shi->vn); - - shi->vn[0]+= dot*nor[0]; - shi->vn[1]+= dot*nor[1]; - shi->vn[2]+= dot*nor[2]; - } + + /* prevent bump to become negative normal */ + nor[0]= Tnor*tex->norfac*texres.nor[0]; + nor[1]= Tnor*tex->norfac*texres.nor[1]; + nor[2]= Tnor*tex->norfac*texres.nor[2]; + + dot= 0.5f + 0.5f*INPR(nor, shi->vn); + + shi->vn[0]+= dot*nor[0]; + shi->vn[1]+= dot*nor[1]; + shi->vn[2]+= dot*nor[2]; } Normalize(shi->vn); @@ -2525,6 +2525,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) ShadeInputUV *suv= &shi->uv[shi->actuv]; int a; + if(R.r.scemode & R_NO_TEX) return; + if(firsttime) { BLI_lock_thread(LOCK_IMAGE); if(firsttime) { diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 94a715162a0..91c7b2b44a8 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3299,7 +3299,7 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu) if(ob==G.obedit) { nu= lastnu; - if(nu==NULL) nu= editNurb.first; + if(nu==NULL) nu= lastnu= editNurb.first; if(nu) { if (ob->type==OB_CURVE) { uiDefBut(block, LABEL, 0, "Tilt", @@ -5070,8 +5070,6 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me) uiBlockEndAlign(block); - uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation"); - uiDefButC(block, MENU, REDRAWBUTSEDIT, "Edge Alt-Select Mode%t|Loop Select%x0|Tag Edges (Seam)%x1|Tag Edges (Sharp)%x2|Tag Edges (Sharp)%x3|Tag Edges (Bevel)%x4",1125,88,150,19, &G.scene->toolsettings->edge_mode, 0, 0, 0, 0, "Operation to use when Alt+RMB on edges, Use Alt+Shift+RMB to tag the shortest path from the active edge"); uiBlockBeginAlign(block); @@ -5322,7 +5320,7 @@ static void editing_panel_links(Object *ob) uiDefBut(block, BUT, B_POSEGRP_ADD, "Add Group", xco,110,140,20, 0, 21, 0, 0, 0, "Add a new Bone Group for the Pose"); uiBlockEndAlign(block); - /* colour set for 'active' group */ + /* color set for 'active' group */ if (pose->active_group && grp) { uiBlockBeginAlign(block); menustr= build_colorsets_menustr(); @@ -5339,7 +5337,7 @@ static void editing_panel_links(Object *ob) memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); } else { - /* init custom colours with a generic multi-colour rgb set, if not initialised already */ + /* init custom colors with a generic multi-color rgb set, if not initialised already */ if (grp->cs.solid[0] == 0) { /* define for setting colors in theme below */ #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; @@ -5521,7 +5519,7 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned uiDefButC(block,ROW,B_NOP,"Sub",cx+89,cy,89,19,&sculptmode_brush()->dir,15.0,2.0,0, 0,"Subtract depth from model [Shift]"); } if(sd->brush_type!=GRAB_BRUSH) - uiDefButBitC(block, TOG, SCULPT_BRUSH_AIRBRUSH, 0, "Airbrush", cx+178,cy,89,19, &sculptmode_brush()->flag,0,0,0,0, "Brush makes changes without waiting for the mouse to move"); + uiDefButBitC(block, TOG, SCULPT_BRUSH_AIRBRUSH, B_NOP, "Airbrush", cx+178,cy,89,19, &sculptmode_brush()->flag,0,0,0,0, "Brush makes changes without waiting for the mouse to move"); cy-= 20; uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels"); cy-= 20; @@ -5534,9 +5532,9 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned uiDefBut( block,LABEL,B_NOP,"Symmetry",cx,cy,90,19,NULL,0,0,0,0,""); cy-= 20; uiBlockBeginAlign(block); - uiDefButBitC(block, TOG, SYMM_X, 0, "X", cx,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across X axis"); - uiDefButBitC(block, TOG, SYMM_Y, 0, "Y", cx+40,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across Y axis"); - uiDefButBitC(block, TOG, SYMM_Z, 0, "Z", cx+80,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across Z axis"); + uiDefButBitC(block, TOG, SYMM_X, B_NOP, "X", cx,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across X axis"); + uiDefButBitC(block, TOG, SYMM_Y, B_NOP, "Y", cx+40,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across Y axis"); + uiDefButBitC(block, TOG, SYMM_Z, B_NOP, "Z", cx+80,cy,40,19, &sd->symm, 0,0,0,0, "Mirror brush across Z axis"); uiBlockEndAlign(block); @@ -5545,9 +5543,9 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned uiDefBut( block,LABEL,B_NOP,"LockAxis",cx+140,cy,90,19,NULL,0,0,0,0,""); cy-= 20; uiBlockBeginAlign(block); - uiDefButBitC(block, TOG, AXISLOCK_X, 0, "X", cx+140,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain X axis"); - uiDefButBitC(block, TOG, AXISLOCK_Y, 0, "Y", cx+180,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain Y axis"); - uiDefButBitC(block, TOG, AXISLOCK_Z, 0, "Z", cx+220,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain Z axis"); + uiDefButBitC(block, TOG, AXISLOCK_X, B_NOP, "X", cx+140,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain X axis"); + uiDefButBitC(block, TOG, AXISLOCK_Y, B_NOP, "Y", cx+180,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain Y axis"); + uiDefButBitC(block, TOG, AXISLOCK_Z, B_NOP, "Z", cx+220,cy,40,19, &sd->axislock, 0,0,0,0, "Constrain Z axis"); uiBlockEndAlign(block); @@ -5584,7 +5582,7 @@ void sculptmode_draw_interface_brush(uiBlock *block, unsigned short cx, unsigned if(sd->brush_type == DRAW_BRUSH) uiDefButC(block,NUM,B_NOP, "View", cx,cy,80,19, &sculptmode_brush()->view, 0,10,20,0,"Pulls brush direction towards view"); cy-= 20; - uiDefButBitC(block, TOG, SCULPT_BRUSH_ANCHORED, 0, "Anchored", cx,cy,80,19, &sculptmode_brush()->flag, 0,0,0,0, "Keep the brush center anchored to the initial location"); + uiDefButBitC(block, TOG, SCULPT_BRUSH_ANCHORED, B_NOP, "Anchored", cx,cy,80,19, &sculptmode_brush()->flag, 0,0,0,0, "Keep the brush center anchored to the initial location"); uiBlockEndAlign(block); /* Draw curve */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 9b0a7c23759..ec2cea46904 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -978,7 +978,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); /* IK Target */ - uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco, *yco-24, 80, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); /* Draw target parameters */ uiBlockBeginAlign(block); @@ -3006,9 +3006,14 @@ void do_effects_panels(unsigned short event) case B_PART_INIT_CHILD: case B_PART_RECALC_CHILD: if(psys) { + Base *base; + Object *bob; + ParticleSystem *bpsys; + int flush; + nr=0; - for(psys=ob->particlesystem.first; psys; psys=psys->next){ - if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + for(bpsys=ob->particlesystem.first; bpsys; bpsys=bpsys->next){ + if(ELEM(bpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) nr++; } if(nr) @@ -3016,6 +3021,21 @@ void do_effects_panels(unsigned short event) else ob->transflag &= ~OB_DUPLIPARTS; + if(psys->part->type==PART_REACTOR) + if(psys->target_ob) + DAG_object_flush_update(G.scene, psys->target_ob, OB_RECALC_DATA); + + for(base = G.scene->base.first; base; base= base->next) { + bob= base->object; + flush= 0; + for(bpsys=bob->particlesystem.first; bpsys; bpsys=bpsys->next) + if(bpsys->part==psys->part) + flush= 1; + + if(flush) + DAG_object_flush_update(G.scene, bob, OB_RECALC_DATA); + } + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSOBJECT, 0); @@ -4117,8 +4137,9 @@ static void object_panel_particle_children(Object *ob) uiDefButF(block, NUM, B_PART_REDRAW, "Rand:", butx+butw/2,buty,butw/2,buth, &part->childrandsize, 0.0, 1.0, 10, 1, "Random variation to the size of the child particles"); } if(part->childtype == PART_CHILD_FACES) { - uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces"); - uiDefButBitI(block, TOG, PART_CHILD_SEAMS, B_PART_DISTR_CHILD, "Use Seams", butx+butw/2,buty,butw/2,buth, &part->flag, 0, 0, 0, 0, "Use seams to determine parents"); + /* only works if children could be emitted from volume, but that option isn't available now */ + /*uiDefButF(block, NUM, B_PART_REDRAW, "Spread:",butx,(buty-=buth),butw/2,buth, &part->childspread, -1.0, 1.0, 10, 1, "Spread children from the faces");*/ + uiDefButBitI(block, TOG, PART_CHILD_SEAMS, B_PART_DISTR_CHILD, "Use Seams", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Use seams to determine parents"); } uiBlockEndAlign(block); diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index e24101786a3..89b0864cec5 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -50,6 +50,7 @@ #include "BKE_sound.h" #include "BKE_packedFile.h" #include "BKE_utildefines.h" +#include "BKE_idprop.h" #include "BLI_blenlib.h" @@ -109,6 +110,7 @@ #include <ffmpeg/avcodec.h> /* for PIX_FMT_* and CODEC_ID_* */ #include <ffmpeg/avformat.h> +#include <ffmpeg/opt.h> static int ffmpeg_preset_sel = 0; @@ -1284,6 +1286,10 @@ void do_sequencer_panels(unsigned short event) Sequence *last_seq = get_last_seq(); ScrArea * sa; + if (!last_seq) { + return; + } + switch(event) { case B_SEQ_BUT_PLUGIN: case B_SEQ_BUT_EFFECT: @@ -1321,6 +1327,7 @@ void do_sequencer_panels(unsigned short event) allqueue(REDRAWALL, 0); } else { allqueue(REDRAWSEQ, 0); + allqueue(REDRAWBUTSSCENE, 0); } } @@ -1402,6 +1409,8 @@ void playback_anim(void) #ifdef WITH_FFMPEG static void set_ffmpeg_preset(int preset); +static int ffmpeg_property_add_string(const char * type, const char * str); +static char ffmpeg_option_to_add[255] = ""; #endif void do_render_panels(unsigned short event) @@ -1689,6 +1698,20 @@ void do_render_panels(unsigned short event) } allqueue(REDRAWBUTSSCENE, 0); allqueue(REDRAWOOPS, 0); +#ifdef WITH_FFMPEG + case B_ADD_FFMPEG_AUDIO_OPTION: + if (ffmpeg_property_add_string("audio", ffmpeg_option_to_add)){ + *ffmpeg_option_to_add = 0; + } + allqueue(REDRAWBUTSSCENE, 0); + break; + case B_ADD_FFMPEG_VIDEO_OPTION: + if (ffmpeg_property_add_string("video", ffmpeg_option_to_add)){ + *ffmpeg_option_to_add = 0; + } + allqueue(REDRAWBUTSSCENE, 0); + break; +#endif } } @@ -1833,13 +1856,14 @@ static char* ffmpeg_preset_pup(void) static char string[2048]; char formatstring[2048]; - strcpy(formatstring, "FFMpeg preset: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d"); + strcpy(formatstring, "FFMpeg preset: %%t|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d|%s %%x%d"); sprintf(string, formatstring, "", FFMPEG_PRESET_NONE, "DVD", FFMPEG_PRESET_DVD, "SVCD", FFMPEG_PRESET_SVCD, "VCD", FFMPEG_PRESET_VCD, - "DV", FFMPEG_PRESET_DV); + "DV", FFMPEG_PRESET_DV, + "H264", FFMPEG_PRESET_H264); return string; } @@ -2274,6 +2298,442 @@ static void render_panel_anim(void) } #ifdef WITH_FFMPEG + +static void ffmpeg_property_del(void *type, void *prop_) +{ + struct IDProperty *prop = (struct IDProperty *) prop_; + IDProperty * group; + + if (!G.scene->r.ffcodecdata.properties) { + return; + } + + group = IDP_GetPropertyFromGroup( + G.scene->r.ffcodecdata.properties, (char*) type); + if (group && prop) { + IDP_RemFromGroup(group, prop); + IDP_FreeProperty(prop); + MEM_freeN(prop); + } + allqueue(REDRAWBUTSSCENE, 0); +} + +static IDProperty * ffmpeg_property_add( + char * type, int opt_index, int parent_index) +{ + AVCodecContext c; + const AVOption * o; + const AVOption * parent; + IDProperty * group; + IDProperty * prop; + IDPropertyTemplate val; + int idp_type; + char name[256]; + + avcodec_get_context_defaults(&c); + + o = c.av_class->option + opt_index; + parent = c.av_class->option + parent_index; + + if (!G.scene->r.ffcodecdata.properties) { + IDPropertyTemplate val; + + G.scene->r.ffcodecdata.properties + = IDP_New(IDP_GROUP, val, "ffmpeg"); + } + + group = IDP_GetPropertyFromGroup( + G.scene->r.ffcodecdata.properties, (char*) type); + + if (!group) { + IDPropertyTemplate val; + + group = IDP_New(IDP_GROUP, val, (char*) type); + IDP_AddToGroup(G.scene->r.ffcodecdata.properties, group); + } + + if (parent_index) { + sprintf(name, "%s:%s", parent->name, o->name); + } else { + strcpy(name, o->name); + } + + fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n", + type, parent_index, opt_index, name); + + prop = IDP_GetPropertyFromGroup(group, name); + if (prop) { + return prop; + } + + switch (o->type) { + case FF_OPT_TYPE_INT: + case FF_OPT_TYPE_INT64: + val.i = o->default_val; + idp_type = IDP_INT; + break; + case FF_OPT_TYPE_DOUBLE: + case FF_OPT_TYPE_FLOAT: + val.f = o->default_val; + idp_type = IDP_FLOAT; + break; + case FF_OPT_TYPE_STRING: + val.str = " "; + idp_type = IDP_STRING; + break; + case FF_OPT_TYPE_CONST: + val.i = 1; + idp_type = IDP_INT; + break; + default: + return NULL; + } + prop = IDP_New(idp_type, val, name); + IDP_AddToGroup(group, prop); + return prop; +} + +/* not all versions of ffmpeg include that, so here we go ... */ + +static const AVOption *my_av_find_opt(void *v, const char *name, + const char *unit, int mask, int flags){ + AVClass *c= *(AVClass**)v; + const AVOption *o= c->option; + + for(;o && o->name; o++){ + if(!strcmp(o->name, name) && + (!unit || (o->unit && !strcmp(o->unit, unit))) && + (o->flags & mask) == flags ) + return o; + } + return NULL; +} + +static int ffmpeg_property_add_string(const char * type, const char * str) +{ + AVCodecContext c; + const AVOption * o = 0; + const AVOption * p = 0; + char name_[128]; + char * name; + char * param; + IDProperty * prop; + + avcodec_get_context_defaults(&c); + + strncpy(name_, str, 128); + + name = name_; + while (*name == ' ') name++; + + param = strchr(name, ':'); + + if (!param) { + param = strchr(name, ' '); + } + if (param) { + *param++ = 0; + while (*param == ' ') param++; + } + + o = my_av_find_opt(&c, name, NULL, 0, 0); + if (!o) { + return FALSE; + } + if (param && o->type == FF_OPT_TYPE_CONST) { + return FALSE; + } + if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { + p = my_av_find_opt(&c, param, o->unit, 0, 0); + prop = ffmpeg_property_add( + (char*) type, p - c.av_class->option, + o - c.av_class->option); + } else { + prop = ffmpeg_property_add( + (char*) type, o - c.av_class->option, 0); + } + + + if (!prop) { + return FALSE; + } + + if (param && !p) { + switch (prop->type) { + case IDP_INT: + IDP_Int(prop) = atoi(param); + break; + case IDP_FLOAT: + IDP_Float(prop) = atof(param); + break; + case IDP_STRING: + strncpy(IDP_String(prop), param, prop->len); + break; + } + } + return TRUE; +} + +static void ffmpeg_property_add_using_menu(void * type, int opt_indices) +{ + int opt_index = opt_indices & 65535; + int parent_index = opt_indices >> 16; + + ffmpeg_property_add((char*) type, opt_index, parent_index); + + allqueue(REDRAWBUTSSCENE, 0); +} + +static uiBlock *ffmpeg_property_add_submenu(AVOption * parent, char * type) +{ + AVCodecContext c; + const AVOption * o; + uiBlock *block; + int yco = 0; + int flags = 0; + int parent_index = 0; + + if (strcmp(type, "audio") == 0) { + flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM; + } else if (strcmp(type, "video") == 0) { + flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM; + } else { + return NULL; + } + + block= uiNewBlock(&curarea->uiblocks, "ffmpeg_property_add_submenu", + UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, ffmpeg_property_add_using_menu, type); + + avcodec_get_context_defaults(&c); + + if (parent) { + parent_index = (parent - c.av_class->option); + } + + for(o = c.av_class->option; o && o->name; o++){ + if (o->help && + (strstr(o->help, "experimental") + || strstr(o->help, "obsolete") + || strstr(o->help, "useless") + || strstr(o->help, "deprecated"))) { + continue; + } + if((o->flags & flags) == flags) { + if((!parent && !o->unit) + || (o->unit && parent + && strcmp(o->unit, parent->unit) == 0 + && o->type == FF_OPT_TYPE_CONST)) { + uiDefBut(block, BUTM, B_REDR, + (char*) (o->help && o->help[0] ? + o->help : o->name), + 0, yco, 160, 15, + NULL, 0, 0, 1, + (o - c.av_class->option) | + (parent_index << 16), + ""); + yco -= 16; + } + } + } + + uiTextBoundsBlock(block, 50); + uiBlockSetDirection(block, UI_RIGHT); + + return block; +} + +static uiBlock *ffmpeg_property_add_submenu_audio(void* opt) +{ + return ffmpeg_property_add_submenu((AVOption*) opt, "audio"); +} + +static uiBlock *ffmpeg_property_add_submenu_video(void* opt) +{ + return ffmpeg_property_add_submenu((AVOption*) opt, "video"); +} + +static uiBlock *ffmpeg_property_add_menu(void* type_) +{ + char * type = (char*) type_; + AVCodecContext c; + const AVOption * o; + uiBlock *block; + int yco = 0; + int flags = 0; + uiBlockFuncFP add_submenu = NULL; + + if (strcmp(type, "audio") == 0) { + flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM; + add_submenu = ffmpeg_property_add_submenu_audio; + } else if (strcmp(type, "video") == 0) { + flags = AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM; + add_submenu = ffmpeg_property_add_submenu_video; + } else { + return NULL; + } + + block= uiNewBlock(&curarea->uiblocks, "ffmpeg_property_add_menu", + UI_EMBOSSP, UI_HELV, curarea->win); + + avcodec_get_context_defaults(&c); + + for(o = c.av_class->option; o && o->name; o++){ + if((o->flags & flags) == flags) { + if (o->type == FF_OPT_TYPE_CONST) { + continue; + } + if (o->help && + (strstr(o->help, "experimental") + || strstr(o->help, "obsolete") + || strstr(o->help, "useless") + || strstr(o->help, "deprecated"))) { + continue; + } + + if (o->unit) { + + uiDefIconTextBlockBut( + block, + add_submenu, + (void*) o, + ICON_RIGHTARROW_THIN, + (char*) (o->help ? + o->help : o->name), + 0, yco, 160, 15, ""); + yco -= 16; + } + } + } + + uiDefIconTextBlockBut( + block, + add_submenu, + NULL, + ICON_RIGHTARROW_THIN, + "Value / string options", + 0, yco, 160, 15, ""); + + uiTextBoundsBlock(block, 50); + uiBlockSetDirection(block, UI_DOWN); + + return block; +} + +static int render_panel_ffmpeg_property_option( + uiBlock *block, int xofs, int yofs, IDProperty * curr, + const char * type) +{ + AVCodecContext c; + const AVOption * o; + uiBut *but; + char name[128]; + char * param; + + strcpy(name, curr->name); + param = strchr(name, ':'); + + if (param) { + *param++ = 0; + } + + avcodec_get_context_defaults(&c); + + o = my_av_find_opt(&c, param ? param : name, NULL, 0, 0); + if (!o) { + return yofs; + } + + switch (curr->type) { + case IDP_STRING: + uiDefBut(block, TEX, + B_REDR, curr->name, + xofs,yofs, 200,19, + IDP_String(curr), + 0.0, curr->len - 1, 100, 0, + (char*) o->help); + break; + case IDP_FLOAT: + uiDefButF(block, NUM, B_REDR, curr->name, + xofs, yofs, 200, 19, + &IDP_Float(curr), + o->min, o->max, 0, 0, (char*) o->help); + break; + case IDP_INT: + if (o->type == FF_OPT_TYPE_CONST) { + uiDefButBitI(block, TOG, 1, B_REDR, + curr->name, + xofs, yofs, 200, 19, + &IDP_Int(curr), + 0, 1, 0,0, (char*) o->help); + } else { + uiDefButI(block, NUM, B_REDR, curr->name, + xofs, yofs, 200, 19, + &IDP_Int(curr), + o->min, o->max, 0, 0, (char*) o->help); + } + break; + } + + but = uiDefIconBut(block, BUT, B_REDR, VICON_X, + xofs + 220, yofs, 16, 16, NULL, + 0.0, 0.0, 0.0, 0.0, "Delete property"); + + uiButSetFunc(but, ffmpeg_property_del, (void*) type, curr); + + yofs -= 25; + + return yofs; +} + +static int render_panel_ffmpeg_properties(uiBlock *block, const char * type, + int xofs, int yofs) +{ + short event = B_NOP; + + yofs -= 5; + + if (strcmp(type, "audio") == 0) { + event = B_ADD_FFMPEG_AUDIO_OPTION; + } else if (strcmp(type, "video") == 0) { + event = B_ADD_FFMPEG_VIDEO_OPTION; + } + + uiDefBut(block, TEX, event, "", xofs, yofs, + 170, 19, ffmpeg_option_to_add, 0.0, 255.0, 100, 0, + "FFMPEG option to add"); + + uiDefBut(block, BUT, event, "Add", xofs+170,yofs, + 30, 19, 0, 0, 0, 0, 0, + "Add FFMPEG option"); + + uiDefBlockBut(block, ffmpeg_property_add_menu, (void*) type, + "Menu", xofs + 200, yofs, 40, 20, + "Add FFMPEG option using menu"); + yofs -= 20; + + if (G.scene->r.ffcodecdata.properties) { + IDProperty * prop; + void * iter; + IDProperty * curr; + + prop = IDP_GetPropertyFromGroup( + G.scene->r.ffcodecdata.properties, (char*) type); + if (prop) { + iter = IDP_GetGroupIterator(prop); + + while ((curr = IDP_GroupIterNext(iter)) != NULL) { + yofs = render_panel_ffmpeg_property_option( + block, xofs, yofs, curr, type); + } + } + } + + uiNewPanelHeight(block, 204-yofs); + + return yofs; +} + static void set_ffmpeg_preset(int preset) { int isntsc = (G.scene->r.frs_sec != 25); @@ -2321,6 +2781,32 @@ static void set_ffmpeg_preset(int preset) G.scene->r.xsch = 720; G.scene->r.ysch = isntsc ? 480 : 576; break; + case FFMPEG_PRESET_H264: + G.scene->r.ffcodecdata.type = FFMPEG_AVI; + G.scene->r.ffcodecdata.codec = CODEC_ID_H264; + G.scene->r.ffcodecdata.video_bitrate = 6000; + G.scene->r.ffcodecdata.gop_size = isntsc ? 18 : 15; + G.scene->r.ffcodecdata.rc_max_rate = 9000; + G.scene->r.ffcodecdata.rc_min_rate = 0; + G.scene->r.ffcodecdata.rc_buffer_size = 224*8; + G.scene->r.ffcodecdata.mux_packet_size = 2048; + G.scene->r.ffcodecdata.mux_rate = 10080000; + + ffmpeg_property_add_string("video", "coder:vlc"); + ffmpeg_property_add_string("video", "flags:loop"); + ffmpeg_property_add_string("video", "cmp:chroma"); + ffmpeg_property_add_string("video", "partitions:parti4x4"); + ffmpeg_property_add_string("video", "partitions:partp8x8"); + ffmpeg_property_add_string("video", "partitions:partb8x8"); + ffmpeg_property_add_string("video", "me:hex"); + ffmpeg_property_add_string("video", "subq:5"); + ffmpeg_property_add_string("video", "me_range:16"); + ffmpeg_property_add_string("video", "keyint_min:25"); + ffmpeg_property_add_string("video", "sc_threshold:40"); + ffmpeg_property_add_string("video", "i_qfactor:0.71"); + ffmpeg_property_add_string("video", "b_strategy:1"); + + break; } } @@ -2360,8 +2846,10 @@ static void render_panel_ffmpeg_video(void) &G.scene->r.ffcodecdata.video_bitrate, 1, 14000, 0, 0, "Video bitrate(kb/s)"); uiDefButI(block, NUM, B_DIFF, "Min Rate", - xcol1, yofs+22, 110, 20, &G.scene->r.ffcodecdata.rc_min_rate, - 0, 14000, 0, 0, "Rate control: min rate(kb/s)"); + xcol1, yofs+22, 110, 20, + &G.scene->r.ffcodecdata.rc_min_rate, + 0, G.scene->r.ffcodecdata.rc_max_rate, + 0, 0, "Rate control: min rate(kb/s)"); uiDefButI(block, NUM, B_DIFF, "Max Rate", xcol1, yofs, 110, 20, &G.scene->r.ffcodecdata.rc_max_rate, 1, 14000, 0, 0, "Rate control: max rate(kb/s)"); @@ -2394,7 +2882,8 @@ static void render_panel_ffmpeg_video(void) 0, 1, 0,0, "Autosplit output at 2GB boundary."); - if (ELEM(G.scene->r.ffcodecdata.type, FFMPEG_AVI, FFMPEG_MOV)) { + if (ELEM3(G.scene->r.ffcodecdata.type, FFMPEG_AVI, + FFMPEG_MOV, FFMPEG_MKV)) { uiDefBut(block, LABEL, 0, "Codec", xcol1, yofs-44, 110, 20, 0, 0, 0, 0, 0, ""); uiDefButI(block, MENU,B_REDR, ffmpeg_codec_pup(), @@ -2402,6 +2891,8 @@ static void render_panel_ffmpeg_video(void) &G.scene->r.ffcodecdata.codec, 0,0,0,0, "FFMpeg codec to use"); } + + render_panel_ffmpeg_properties(block, "video", xcol1, yofs-86); } static void render_panel_ffmpeg_audio(void) @@ -2431,6 +2922,8 @@ static void render_panel_ffmpeg_audio(void) xcol, yofs-66, 110, 20, &G.scene->r.ffcodecdata.audio_bitrate, 32, 384, 0, 0, "Audio bitrate(kb/s)"); + + render_panel_ffmpeg_properties(block, "audio", xcol, yofs-86); } #endif diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 600632f8776..80ad52a9b00 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2681,7 +2681,8 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiDefButF(block, NUM,B_LAMPREDRAW,"Soft Size", 100,80,200,19, &la->area_size, 0.01, 100.0, 10, 0, "Area light size, doesn't affect energy amount"); uiDefButS(block, NUM,0,"Samples:", 100,60,200,19, &la->ray_samp, 1.0, 16.0, 100, 0, "Sets the amount of samples taken extra (samp x samp)"); - uiDefButF(block, NUM,0,"Threshold:", 100,40,200,19, &la->adapt_thresh, 0.0, 1.0, 100, 0, "Threshold for adaptive sampling, to control what level is considered already in shadow"); + if (la->ray_samp_method == LA_SAMP_HALTON) + uiDefButF(block, NUM,0,"Threshold:", 100,40,200,19, &la->adapt_thresh, 0.0, 1.0, 100, 0, "Threshold for adaptive sampling, to control what level is considered already in shadow"); } else if (la->type == LA_AREA) { uiDefButS(block, MENU, B_REDR, "Adaptive QMC %x1|Constant QMC %x2|Constant Jittered %x0", @@ -2887,8 +2888,8 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockBeginAlign(block); if (ELEM(la->type, LA_LOCAL, LA_SPOT) && (la->falloff_type == LA_FALLOFF_SLIDERS)) { - uiDefButF(block, NUMSLI,B_LAMPPRV,"Linear ", 120,30,180,19,&la->att1, 0.0, 1.0, 0, 0, "Set the linear distance attenuatation for a quad lamp"); - uiDefButF(block, NUMSLI,B_LAMPPRV,"Quad ", 120,10,180,19,&la->att2, 0.0, 1.0, 0, 0, "Set the quadratic distance attenuatation for a quad lamp"); + uiDefButF(block, NUMSLI,B_LAMPPRV,"Linear ", 120,30,180,19,&la->att1, 0.0, 1.0, 0, 0, "Set the linear distance attenuation for a Lin/Quad Weighted lamp"); + uiDefButF(block, NUMSLI,B_LAMPPRV,"Quad ", 120,10,180,19,&la->att2, 0.0, 1.0, 0, 0, "Set the quadratic distance attenuation for a Lin/Quad Weighted lamp"); } else if(la->type==LA_AREA) { if(la->k==0.0) la->k= 1.0; @@ -3288,7 +3289,7 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes) //uiButSetFunc(but, particle_recalc_material, ma, NULL); but=uiDefButBitS(block, TOG3, MAP_PA_KINK, B_MAT_PARTICLE, "Kink", 70,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the kink of child particles"); //uiButSetFunc(but, particle_recalc_material, ma, NULL); - but=uiDefButBitS(block, TOG3, MAP_PA_LENGTH, B_MAT_PARTICLE, "Length",130,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the length of particles"); + but=uiDefButBitS(block, TOG3, MAP_PA_LENGTH, B_MAT_PARTICLE, "Length",130,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the length of child particles"); //uiButSetFunc(but, particle_recalc_material, ma, NULL); but=uiDefButBitS(block, TOG3, MAP_PA_CLUMP, B_MAT_PARTICLE, "Clump", 190,160,60,19, &(mtex->pmapto), 0, 0, 0, 0, "Causes the texture to affect the clump of child particles"); //uiButSetFunc(but, particle_recalc_material, ma, NULL); @@ -3298,10 +3299,10 @@ static void material_panel_map_to(Object *ob, Material *ma, int from_nodes) uiBlockSetCol(block, TH_AUTO); } else { - uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col", 10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic colour of the material"); + uiDefButBitS(block, TOG, MAP_COL, B_MATPRV, "Col", 10,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect basic color of the material"); uiDefButBitS(block, TOG3, MAP_NORM, B_MATPRV, "Nor", 50,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the rendered normal"); - uiDefButBitS(block, TOG, MAP_COLSPEC, B_MATPRV, "Csp", 90,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity colour"); - uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Cmir", 130,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the mirror colour"); + uiDefButBitS(block, TOG, MAP_COLSPEC, B_MATPRV, "Csp", 90,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the specularity color"); + uiDefButBitS(block, TOG, MAP_COLMIR, B_MATPRV, "Cmir", 130,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the mirror color"); uiDefButBitS(block, TOG3, MAP_REF, B_MATPRV, "Ref", 180,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of the materials reflectivity"); uiDefButBitS(block, TOG3, MAP_SPEC, B_MATPRV, "Spec", 220,180,50,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of specularity"); uiDefButBitS(block, TOG3, MAP_AMB, B_MATPRV, "Amb", 270,180,40,19, &(mtex->mapto), 0, 0, 0, 0, "Causes the texture to affect the value of ambient"); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 1a742440e9b..65221dceaf9 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -634,7 +634,7 @@ static void draw_channel_names(void) } else { /* for normal channels - * - use 3 shades of color group/standard colour for 3 indention level + * - use 3 shades of color group/standard color for 3 indention level * - only use group colors if allowed to, and if actually feasible */ if ( !(G.saction->flag & SACTION_NODRAWGCOLORS) && @@ -1254,7 +1254,7 @@ static void draw_key_but(int x, int y, short w, short h, int sel) int xmax= x+w-1, ymax= y+h-1; int xc= (xmin+xmax)/2, yc= (ymin+ymax)/2; - /* interior - hardcoded colours (for selected and unselected only) */ + /* interior - hardcoded colors (for selected and unselected only) */ if (sel) glColor3ub(0xF1, 0xCA, 0x13); else glColor3ub(0xE9, 0xE9, 0xE9); diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 9b8905b782b..73915a69139 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -96,7 +96,7 @@ static ThemeWireColor *bcolor= NULL; /* values of colCode for set_pchan_glcolor */ enum { PCHAN_COLOR_NORMAL = 0, /* normal drawing */ - PCHAN_COLOR_SOLID, /* specific case where "solid" colour is needed */ + PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */ PCHAN_COLOR_CONSTS, /* "constraint" colors (which may/may-not be suppressed) */ PCHAN_COLOR_SPHEREBONE_BASE, /* for the 'stick' of sphere (envelope) bones */ @@ -1186,7 +1186,7 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign /* wire */ if (armflag & ARM_POSEMODE) { if (constflag) { - /* set constraint colours */ + /* set constraint colors */ if (set_pchan_glColor(PCHAN_COLOR_CONSTS, armflag, boneflag, constflag)) { glEnable(GL_BLEND); @@ -1618,7 +1618,7 @@ static void draw_pose_channels(Base *base, int dt) } /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet, - * stick bones and/or wire custom-shpaes are drawn in next loop + * stick bones and/or wire custom-shapes are drawn in next loop */ if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) { /* object tag, for bordersel optim */ @@ -1645,7 +1645,7 @@ static void draw_pose_channels(Base *base, int dt) glPushMatrix(); glMultMatrixf(pchan->pose_mat); - /* prepare colours */ + /* prepare colors */ if (arm->flag & ARM_POSEMODE) set_pchan_colorset(ob, pchan); else { @@ -2090,7 +2090,7 @@ static void draw_pose_paths(Object *ob) for (a=0, fp=fp_start; a<len; a++, fp+=3) { float intensity; /* how faint */ - /* set colour + /* set color * - more intense for active/selected bones, less intense for unselected bones * - black for before current frame, green for current frame, blue for after current frame * - intensity decreases as distance from current frame increases @@ -2131,7 +2131,7 @@ static void draw_pose_paths(Object *ob) BIF_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10); } - /* draw a vertex with this colour */ + /* draw a vertex with this color */ glVertex3fv(fp); } diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 6d1cd244b84..04ba04c51f1 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -367,7 +367,10 @@ static void drawcursor_sima(float xuser_asp, float yuser_asp) int wi, hi; float w, h; - if (!G.obedit || !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE)) return; + if ( !G.obedit || /* only draw cursor in editmode */ + !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE) || /* must have UV's */ + (G.sima->image && G.sima->flag & SI_DRAWTOOL) /* cant be painting */ + ) return; transform_width_height_tface_uv(&wi, &hi); w = (((float)wi)/256.0f)*G.sima->zoom * xuser_asp; @@ -1485,7 +1488,11 @@ static void image_panel_paint(short cntrl) // IMAGE_HANDLER_PAINT uiBlock *block; ID *id; int yco, xco, butw; - + + if ((G.sima->image && (G.sima->flag & SI_DRAWTOOL))==0) { + return; + } + block= uiNewBlock(&curarea->uiblocks, "image_panel_paint", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(IMAGE_HANDLER_PAINT); // for close and esc diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 561024fb74b..1ee30501a1a 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -4228,6 +4228,7 @@ static void draw_forcefield(Object *ob) drawcircball(GL_LINE_LOOP, vec, size, tmat); vec[2]= 1.5*force_val; drawcircball(GL_LINE_LOOP, vec, size, tmat); + vec[2] = 0; /* reset vec for max dist circle */ } else if (pd->forcefield == PFIELD_FORCE) { diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 15b7f3dbe67..52e0d3d6f05 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -3398,12 +3398,12 @@ static float redrawtimes_fps[REDRAW_FRAME_AVERAGE]; static short redrawtime_index; -int update_time(void) +int update_time(int cfra) { static double ltime; double time; - if ((audiostream_pos() != CFRA) + if ((audiostream_pos() != cfra) && (G.scene->audio.flag & AUDIO_SYNC)) { return 0; } @@ -3641,7 +3641,7 @@ void inner_play_anim_loop(int init, int mode) /* make sure that swaptime passed by */ tottime -= swaptime; - while (update_time()) { + while (update_time(CFRA)) { PIL_sleep_ms(1); } @@ -3700,7 +3700,7 @@ int play_anim(int mode) inner_play_prefetch_startup(mode); - update_time(); + update_time(CFRA); inner_play_anim_loop(1, mode); /* 1==init */ diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 656ecda8eac..a44bbc3af0f 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -1530,35 +1530,11 @@ void snap_curs_to_active() if (G.obedit->type == OB_MESH) { /* check active */ - if (G.editMesh->selected.last) { - EditSelection *ese = G.editMesh->selected.last; - if ( ese->type == EDITVERT ) { - EditVert *eve = (EditVert *)ese->data; - VECCOPY(curs, eve->co); - } - else if ( ese->type == EDITEDGE ) { - EditEdge *eed = (EditEdge *)ese->data; - VecAddf(curs, eed->v1->co, eed->v2->co); - VecMulf(curs, 0.5f); - } - else if ( ese->type == EDITFACE ) { - EditFace *efa = (EditFace *)ese->data; - - if (efa->v4) - { - VecAddf(curs, efa->v1->co, efa->v2->co); - VecAddf(curs, curs, efa->v3->co); - VecAddf(curs, curs, efa->v4->co); - VecMulf(curs, 0.25f); - } - else - { - VecAddf(curs, efa->v1->co, efa->v2->co); - VecAddf(curs, curs, efa->v3->co); - VecMulf(curs, 1/3.0f); - } - } + EditSelection ese; + if (EM_get_actSelection(&ese)) { + EM_editselection_center(curs, &ese); } + Mat4MulVecfl(G.obedit->obmat, curs); } } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 9eda96e0edd..12b9cb8919f 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -1161,7 +1161,7 @@ void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[]) memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); } else { - /* init custom colours with a generic multi-colour rgb set, if not initialised already */ + /* init custom colors with a generic multi-color rgb set, if not initialised already */ if (agrp->cs.solid[0] == 0) { /* define for setting colors in theme below */ #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; @@ -1221,7 +1221,7 @@ void sync_pchan2achan_grouping () achan->grp = NULL; BLI_freelistN(&act->groups); - /* loop through all achans, reassigning them to groups (colours are resyncronised) */ + /* loop through all achans, reassigning them to groups (colors are resyncronised) */ last= act->chanbase.last; for (achan= act->chanbase.first; achan && achan!=last; achan= next) { next= achan->next; @@ -2564,7 +2564,7 @@ static void select_poseelement_by_name (char *name, int select) if ((ob==NULL) || (ob->type!=OB_ARMATURE)) return; - if (select == 2) { + if (abs(select) == 2) { for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) pchan->bone->flag &= ~(BONE_ACTIVE); } @@ -3263,6 +3263,8 @@ void borderselect_actionchannels (void) } break; case ACTTYPE_ACHAN: /* action channel */ + case ACTTYPE_FILLIPO: /* expand ipo curves = action channel */ + case ACTTYPE_FILLCON: /* expand constraint channels = action channel */ { bActionChannel *achan= (bActionChannel *)ale->data; @@ -3270,6 +3272,9 @@ void borderselect_actionchannels (void) achan->flag |= ACHAN_SELECTED; else achan->flag &= ~ACHAN_SELECTED; + + /* messy... set active bone */ + select_poseelement_by_name(achan->name, selectmode); } break; case ACTTYPE_CONCHAN: /* constraint channel */ @@ -3293,6 +3298,14 @@ void borderselect_actionchannels (void) } break; } + + /* select action-channel 'owner' */ + if ((ale->owner) && (ale->ownertype == ACTTYPE_ACHAN)) { + bActionChannel *achano= (bActionChannel *)ale->owner; + + /* messy... set active bone */ + select_poseelement_by_name(achano->name, selectmode); + } } ymax=ymin; @@ -3305,6 +3318,7 @@ void borderselect_actionchannels (void) allqueue(REDRAWIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); + allqueue(REDRAWVIEW3D, 0); } } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index f87eb321fc8..172e06f5add 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -55,6 +55,8 @@ #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" #include "DNA_modifier_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -661,9 +663,10 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) Object *ob; bPoseChannel *pchan, *pcha, *pchb; bConstraint *con; - ListBase *npchans; + ListBase *opchans, *npchans; - /* get reference to list of bones in new armature */ + /* get reference to list of bones in original and new armatures */ + opchans= &origArm->pose->chanbase; npchans= &newArm->pose->chanbase; /* let's go through all objects in database */ @@ -682,8 +685,8 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) for (ct= targets.first; ct; ct= ct->next) { /* any targets which point to original armature are redirected to the new one only if: - * - the target isn't the original armature itself - * - the target is one that can be found in newArm + * - the target isn't origArm/newArm itself + * - the target is one that can be found in newArm/origArm */ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) { for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { @@ -699,6 +702,20 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) if (pcha == pchb) break; } } + else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) { + for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { + /* check if either one matches */ + if ( (strcmp(pcha->name, ct->subtarget)==0) || + (strcmp(pchb->name, ct->subtarget)==0) ) + { + ct->tar= origArm; + break; + } + + /* check if both ends have met (to stop checking) */ + if (pcha == pchb) break; + } + } } if (cti->flush_constraint_targets) @@ -721,8 +738,8 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) for (ct= targets.first; ct; ct= ct->next) { /* any targets which point to original armature are redirected to the new one only if: - * - the target isn't the original armature itself - * - the target is one of the bones which were moved into newArm + * - the target isn't origArm/newArm itself + * - the target is one that can be found in newArm/origArm */ if ((ct->tar == origArm) && (ct->subtarget[0] != 0)) { for (pcha=npchans->first, pchb=npchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { @@ -736,7 +753,21 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm) /* check if both ends have met (to stop checking) */ if (pcha == pchb) break; - } + } + } + else if ((ct->tar == newArm) && (ct->subtarget[0] != 0)) { + for (pcha=opchans->first, pchb=opchans->last; pcha && pchb; pcha=pcha->next, pchb=pchb->prev) { + /* check if either one matches */ + if ( (strcmp(pcha->name, ct->subtarget)==0) || + (strcmp(pchb->name, ct->subtarget)==0) ) + { + ct->tar= origArm; + break; + } + + /* check if both ends have met (to stop checking) */ + if (pcha == pchb) break; + } } } @@ -829,12 +860,6 @@ void separate_armature (void) Base *base, *oldbase, *newbase; bArmature *arm; - // 31 Mar 08 \ 11 May 08 - Aligorith: - // currently, this is still too unstable to be enabled for general consumption. - // remove the following two lines to test this tool... you have been warned! - // okee("Not implemented (WIP)"); - // return; - if ( G.vd==0 || (G.vd->lay & G.obedit->lay)==0 ) return; if ( okee("Separate")==0 ) return; @@ -2948,6 +2973,8 @@ void extrude_armature(int forked) newbone->parent = ebone; newbone->flag = ebone->flag & BONE_TIPSEL; // copies it, in case mirrored bone + + if (newbone->parent) newbone->flag |= BONE_CONNECTED; } else { VECCOPY(newbone->head, ebone->head); @@ -2955,6 +2982,10 @@ void extrude_armature(int forked) newbone->parent= ebone->parent; newbone->flag= BONE_TIPSEL; + + if (newbone->parent && ebone->flag & BONE_CONNECTED) { + newbone->flag |= BONE_CONNECTED; + } } newbone->weight= ebone->weight; @@ -2968,8 +2999,6 @@ void extrude_armature(int forked) newbone->segments= 1; newbone->layer= ebone->layer; - if (newbone->parent) newbone->flag |= BONE_CONNECTED; - BLI_strncpy (newbone->name, ebone->name, 32); if (flipbone && forked) { // only set if mirror edit @@ -3827,7 +3856,7 @@ void unique_bone_name (bArmature *arm, char *name) } #define MAXBONENAME 32 -/* helper call for below */ +/* helper call for armature_bone_rename */ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname) { bConstraint *curcon; @@ -3859,6 +3888,7 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) { Object *ob; + Ipo *ipo; char newname[MAXBONENAME]; char oldname[MAXBONENAME]; @@ -3882,7 +3912,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) else return; } else { - Bone *bone= get_named_bone (arm, oldname); + Bone *bone= get_named_bone(arm, oldname); if (bone) { unique_bone_name (arm, newname); @@ -3891,7 +3921,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) else return; } - /* do entire dbase */ + /* do entire dbase - objects */ for (ob= G.main->object.first; ob; ob= ob->id.next) { /* we have the object using the armature */ if (arm==ob->data) { @@ -3913,7 +3943,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) if (ob->pose) { bPoseChannel *pchan = get_pose_channel(ob->pose, oldname); if (pchan) - BLI_strncpy (pchan->name, newname, MAXBONENAME); + BLI_strncpy(pchan->name, newname, MAXBONENAME); } /* check all nla-strips too */ @@ -3959,6 +3989,28 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) } } } + + /* do entire db - ipo's for the drivers */ + for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) { + IpoCurve *icu; + + /* check each curve's driver */ + for (icu= ipo->curve.first; icu; icu= icu->next) { + IpoDriver *icd= icu->driver; + + if ((icd) && (icd->ob)) { + ob= icd->ob; + + if (icu->driver->type == IPO_DRIVER_TYPE_NORMAL) { + if (!strcmp(oldname, icd->name)) + BLI_strncpy(icd->name, newname, MAXBONENAME); + } + else { + /* TODO: pydrivers need to be treated differently */ + } + } + } + } } } diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c index 653e74c70b4..0ad58a5ce4b 100644 --- a/source/blender/src/editconstraint.c +++ b/source/blender/src/editconstraint.c @@ -681,7 +681,7 @@ static void test_constraints (Object *owner, const char substring[]) Bone *bone; bPoseChannel *chan; - bone = get_named_bone( ((bArmature *)owner->data ), substring ); + bone = get_named_bone( ((bArmature *)owner->data), substring ); chan = get_pose_channel(owner->pose, substring); if (bone && chan) { conlist = &chan->constraints; @@ -831,9 +831,9 @@ static void test_bonelist_constraints (Object *owner, ListBase *list) { Bone *bone; - for (bone = list->first; bone; bone=bone->next) { + for (bone = list->first; bone; bone = bone->next) { test_constraints(owner, bone->name); - test_bonelist_constraints (owner, &bone->childbase); + test_bonelist_constraints(owner, &bone->childbase); } } @@ -845,7 +845,7 @@ void object_test_constraints (Object *owner) bArmature *arm= get_armature(owner); if (arm) - test_bonelist_constraints (owner, &arm->bonebase); + test_bonelist_constraints(owner, &arm->bonebase); } } diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index 34dcab09c2a..7572391b383 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -3658,6 +3658,11 @@ void delNurb() } } } + + /* Never allow the order to exceed the number of points */ + if ((nu->type & 7)==CU_NURBS && (nu->pntsu < nu->orderu)) { + nu->orderu = nu->pntsu; + } nu= next; } /* 2nd loop, delete small pieces: just for curves */ @@ -3669,7 +3674,7 @@ void delNurb() bezt= nu->bezt; for(a=0;a<nu->pntsu;a++) { if( BEZSELECTED_HIDDENHANDLES(bezt) ) { - memcpy(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple)); + memmove(bezt, bezt+1, (nu->pntsu-a-1)*sizeof(BezTriple)); nu->pntsu--; a--; event= 1; @@ -3690,7 +3695,7 @@ void delNurb() for(a=0;a<nu->pntsu;a++) { if( bp->f1 & SELECT ) { - memcpy(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint)); + memmove(bp, bp+1, (nu->pntsu-a-1)*sizeof(BPoint)); nu->pntsu--; a--; event= 1; @@ -3704,6 +3709,11 @@ void delNurb() memcpy(bp1, nu->bp, (nu->pntsu)*sizeof(BPoint) ); MEM_freeN(nu->bp); nu->bp= bp1; + + /* Never allow the order to exceed the number of points */ + if ((nu->type & 7)==CU_NURBS && (nu->pntsu < nu->orderu)) { + nu->orderu = nu->pntsu; + } } makeknots(nu, 1, nu->flagu>>1); } diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index d89af858f21..781210cd373 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -151,33 +151,6 @@ int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect) return 1; } -#if 0 // not used -/* returns 0 if not found, otherwise 1 */ -static int facesel_edge_pick(Mesh *me, short *mval, unsigned int *index) -{ - int dist; - unsigned int min = me->totface + 1; - unsigned int max = me->totface + me->totedge + 1; - - if (me->totedge == 0) - return 0; - - if (G.vd->flag & V3D_NEEDBACKBUFDRAW) { - check_backbuf(); - persp(PERSP_VIEW); - } - - *index = sample_backbuf_rect(mval, 50, min, max, &dist,0,NULL); - - if (*index == 0) - return 0; - - (*index)--; - - return 1; -} -#endif - /* only operates on the edit object - this is all thats needed at the moment */ static void uv_calc_center_vector(float *result, Object *ob, EditMesh *em) { diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index a8b2ff761e5..c5dd41e16d5 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -116,6 +116,7 @@ #include "BSE_headerbuttons.h" #include "BSE_node.h" #include "BSE_sequence.h" +#include "BSE_seqaudio.h" #include "BSE_time.h" #include "blendef.h" @@ -5643,7 +5644,7 @@ void ipo_record(void) if(poin) ei1->icu->curval= read_ipo_poin(poin, type); or1= ei1->icu->curval; ei1->icu->flag |= IPO_LOCK; - + if(ei2) { if(ei2->icu==NULL) ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode); @@ -5671,8 +5672,9 @@ void ipo_record(void) } sa= sa->next; } + if(sa) areawinset(sa->win); - + /* can we? */ while(get_mbut()&L_MOUSE) BIF_wait_for_statechange(); data1= MEM_callocN(sizeof(float)*(EFRA-SFRA+1), "data1"); @@ -5681,14 +5683,18 @@ void ipo_record(void) getmouseco_areawin(mvalo); xn= mvalo[0]; yn= mvalo[1]; waitcursor(1); - + tottime= 0.0; swaptime= 1.0/FPS; cfrao= CFRA; cfra=efra= SFRA; sfra= EFRA; - + + if (G.scene->audio.flag & AUDIO_SYNC) { + audiostream_start(cfra); + } + while(afbreek==0) { getmouseco_areawin(mval); @@ -5698,7 +5704,7 @@ void ipo_record(void) else firsttime= 0; set_timecursor(cfra); - + /* do ipo: first all, then the specific ones */ if(anim==2) { do_ob_ipo(ob); @@ -5729,7 +5735,7 @@ void ipo_record(void) /* minimal wait swaptime */ tottime -= swaptime; - while (update_time()) PIL_sleep_ms(1); + while (update_time(cfra)) PIL_sleep_ms(1); screen_swapbuffers(); @@ -5739,8 +5745,18 @@ void ipo_record(void) mvalo[1]= mval[1]; if(anim || (G.qual & LR_CTRLKEY)) { - cfra++; - if(cfra>EFRA) cfra= SFRA; + if (G.scene->audio.flag & AUDIO_SYNC) { + cfra = audiostream_pos(); + } else { + cfra++; + } + if(cfra>EFRA) { + cfra= SFRA; + if (G.scene->audio.flag & AUDIO_SYNC) { + audiostream_stop(); + audiostream_start( cfra ); + } + } } } @@ -5793,6 +5809,9 @@ void ipo_record(void) editipo_changed(G.sipo, 0); do_ipo(G.sipo->ipo); waitcursor(0); + if (G.scene->audio.flag & AUDIO_SYNC) { + audiostream_stop(); + } allqueue(REDRAWVIEW3D, 0); if(sa) scrarea_queue_headredraw(sa); /* headerprint */ diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index eb8d3a12322..088c85edc56 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -103,6 +103,35 @@ EditFace * EM_get_actFace(int sloppy) return NULL; } +int EM_get_actSelection(EditSelection *ese) +{ + EditSelection *ese_last = G.editMesh->selected.last; + EditFace *efa = EM_get_actFace(0); + + ese->next = ese->prev = NULL; + + if (ese_last) { + if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */ + if (efa) { + ese->data = (void *)efa; + } else { + ese->data = ese_last->data; + } + ese->type = EDITFACE; + } else { + ese->data = ese_last->data; + ese->type = ese_last->type; + } + } else if (efa) { /* no */ + ese->data = (void *)efa; + ese->type = EDITFACE; + } else { + ese->data = NULL; + return 0; + } + return 1; +} + /* ********* Selection History ************ */ static int EM_check_selection(void *data) { diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 81d79de08c5..d5e34779173 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -1458,7 +1458,7 @@ void mesh_copy_menu(void) eed_act = (EditEdge*)ese->data; - ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Length%x2"); + ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3"); if (ret<1) return; eed_len_act = VecLenf(eed_act->v1->co, eed_act->v2->co); @@ -1472,8 +1472,16 @@ void mesh_copy_menu(void) } } break; + case 2: /* copy bevel weight */ + for(eed=em->edges.first; eed; eed=eed->next) { + if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) { + eed->bweight = eed_act->bweight; + change = 1; + } + } + break; - case 2: /* copy length */ + case 3: /* copy length */ for(eed=em->edges.first; eed; eed=eed->next) { if (eed->f & SELECT && eed != eed_act) { @@ -3187,12 +3195,14 @@ void select_non_manifold(void) } /* select isolated verts */ - eve= em->verts.first; - while(eve) { - if (eve->f1 == 0) { - if (!eve->h) eve->f |= SELECT; + if(G.scene->selectmode & SCE_SELECT_VERTEX) { + eve= em->verts.first; + while(eve) { + if (eve->f1 == 0) { + if (!eve->h) eve->f |= SELECT; + } + eve= eve->next; } - eve= eve->next; } countall(); diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 7d589e160c8..d4ebe181218 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -6758,7 +6758,7 @@ void mesh_mirror_uvs(void) { EditMesh *em = G.editMesh; EditFace *efa; - short change = 0; + short change = 0, altaxis; MTFace *tf; float u1, v1; @@ -6767,32 +6767,64 @@ void mesh_mirror_uvs(void) return; } + altaxis = (G.qual == LR_SHIFTKEY); + for(efa=em->faces.first; efa; efa=efa->next) { if (efa->f & SELECT) { tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - u1= tf->uv[0][0]; - v1= tf->uv[0][1]; - if(efa->v4) { - tf->uv[0][0]= tf->uv[3][0]; - tf->uv[0][1]= tf->uv[3][1]; - - tf->uv[3][0]= u1; - tf->uv[3][1]= v1; - + if (altaxis) { u1= tf->uv[1][0]; v1= tf->uv[1][1]; + if(efa->v4) { + + tf->uv[1][0]= tf->uv[2][0]; + tf->uv[1][1]= tf->uv[2][1]; + + tf->uv[2][0]= u1; + tf->uv[2][1]= v1; - tf->uv[1][0]= tf->uv[2][0]; - tf->uv[1][1]= tf->uv[2][1]; + u1= tf->uv[3][0]; + v1= tf->uv[3][1]; + + tf->uv[3][0]= tf->uv[0][0]; + tf->uv[3][1]= tf->uv[0][1]; - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; - } - else { - tf->uv[0][0]= tf->uv[2][0]; - tf->uv[0][1]= tf->uv[2][1]; - tf->uv[2][0]= u1; - tf->uv[2][1]= v1; + tf->uv[0][0]= u1; + tf->uv[0][1]= v1; + } + else { + tf->uv[1][0]= tf->uv[2][0]; + tf->uv[1][1]= tf->uv[2][1]; + tf->uv[2][0]= u1; + tf->uv[2][1]= v1; + } + + } else { + u1= tf->uv[0][0]; + v1= tf->uv[0][1]; + if(efa->v4) { + + tf->uv[0][0]= tf->uv[1][0]; + tf->uv[0][1]= tf->uv[1][1]; + + tf->uv[1][0]= u1; + tf->uv[1][1]= v1; + + u1= tf->uv[3][0]; + v1= tf->uv[3][1]; + + tf->uv[3][0]= tf->uv[2][0]; + tf->uv[3][1]= tf->uv[2][1]; + + tf->uv[2][0]= u1; + tf->uv[2][1]= v1; + } + else { + tf->uv[0][0]= tf->uv[1][0]; + tf->uv[0][1]= tf->uv[1][1]; + tf->uv[1][0]= u1; + tf->uv[1][1]= v1; + } } change = 1; } @@ -6858,27 +6890,38 @@ void mesh_mirror_colors(void) { EditMesh *em = G.editMesh; EditFace *efa; - short change = 0; + short change = 0, altaxis; MCol tmpcol, *mcol; if (!EM_vertColorCheck()) { error("mesh has no color layers"); return; } + altaxis = (G.qual == LR_SHIFTKEY); + for(efa=em->faces.first; efa; efa=efa->next) { if (efa->f & SELECT) { mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - tmpcol= mcol[0]; - - mcol[0]= mcol[1]; - mcol[1]= mcol[2]; - - if(efa->v4) { - mcol[2]= mcol[3]; - mcol[3]= tmpcol; - } - else { + if (altaxis) { + tmpcol= mcol[1]; + mcol[1]= mcol[2]; mcol[2]= tmpcol; + + if(efa->v4) { + tmpcol= mcol[0]; + mcol[0]= mcol[3]; + mcol[3]= tmpcol; + } + } else { + tmpcol= mcol[0]; + mcol[0]= mcol[1]; + mcol[1]= tmpcol; + + if(efa->v4) { + tmpcol= mcol[2]; + mcol[2]= mcol[3]; + mcol[3]= tmpcol; + } } change = 1; } diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 6a703eaabde..afafc4f2590 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -198,7 +198,7 @@ static int image_detect_file_sequence(int *start_p, int *frames_p, char *str) unsigned short numlen; sfile= scrarea_find_space_of_type(curarea, SPACE_FILE); - if(sfile==0) + if(sfile==NULL || sfile->filelist==NULL) return 0; /* find first frame */ diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index bd1c265f2a1..c26e01d994b 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -2891,7 +2891,7 @@ void enter_meta(void) ed= G.scene->ed; if(ed==0) return; - if(last_seq==0 || last_seq->type!=SEQ_META || last_seq->flag==0) { + if(last_seq==0 || last_seq->type!=SEQ_META || (last_seq->flag & SELECT)==0) { exit_meta(); return; } diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index f5cf29528f3..5f8485267bc 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -1217,7 +1217,7 @@ void snap_menu_sima(void) short event; if( is_uv_tface_editing_allowed()==0 || !G.v2d) return; /* !G.v2d should never happen */ - event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Selection -> Adjacent Unselected%x3|Cursor -> Pixel%x4|Cursor -> Selection%x5"); + event = pupmenu("Snap %t|Selection -> Pixels%x1|Selection -> Cursor%x2|Selection -> Adjacent Unselected%x3|Cursor -> Selection%x4|Cursor -> Pixel%x5"); switch (event) { case 1: if (snap_uv_sel_to_pixels()) { @@ -1238,13 +1238,13 @@ void snap_menu_sima(void) } break; case 4: - snap_uv_curs_to_pixels(); - scrarea_queue_winredraw(curarea); - break; - case 5: if (snap_uv_curs_to_sel()) allqueue(REDRAWIMAGE, 0); break; + case 5: + snap_uv_curs_to_pixels(); + scrarea_queue_winredraw(curarea); + break; } } diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index b7fbddc520f..e3ec69975de 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -2764,7 +2764,7 @@ void fly(void) do_screenhandlers(G.curscreen); /* advance the next frame */ - /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to teh view */ + /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ if (G.vd->persp==V3D_CAMOB) { G.vd->persp= V3D_PERSP; /*set this so setviewmatrixview3d uses the ofs and quat instead of the camera */ setviewmatrixview3d(); diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 3d5e39fe942..ac1c0fb7dfe 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -1578,8 +1578,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile) BLI_strncpy(sfile->dir, butname, sizeof(sfile->dir)); /* strip the trailing slash if its a real dir */ - if (strlen(butname)!=1) - butname[strlen(butname)-1]=0; + BLI_del_slash(butname); if(sfile->type & FILE_UNIX) { if (!BLI_exists(butname)) { @@ -1623,6 +1622,11 @@ static void do_filesel_buttons(short event, SpaceFile *sfile) BLI_strncpy(sfile->dir, lib->filename, sizeof(sfile->dir)); BLI_make_exist(sfile->dir); BLI_cleanup_dir(G.sce, sfile->dir); + + /* forced re-reading the blend file */ + if(sfile->libfiledata) BLO_blendhandle_close(sfile->libfiledata); + sfile->libfiledata= 0; + freefilelist(sfile); sfile->ofs= 0; scrarea_queue_winredraw(curarea); diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index bd170d646eb..5df724cc006 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -245,9 +245,24 @@ void do_image_buttons(unsigned short event) break; } case B_SIMACLONEBROWSE: - if (settings->imapaint.brush) - if (brush_clone_image_set_nr(settings->imapaint.brush, G.sima->menunr)) + if(settings->imapaint.brush) { + Brush *brush= settings->imapaint.brush; + + if(G.sima->menunr== -2) { + if(G.qual & LR_CTRLKEY) { + activate_databrowse_imasel((ID *)brush->clone.image, ID_IM, 0, B_SIMACLONEBROWSE, + &G.sima->menunr, do_image_buttons); + } else { + activate_databrowse((ID *)brush->clone.image, ID_IM, 0, B_SIMACLONEBROWSE, + &G.sima->menunr, do_image_buttons); + } + break; + } + if(G.sima->menunr < 0) break; + + if(brush_clone_image_set_nr(brush, G.sima->menunr)) allqueue(REDRAWIMAGE, 0); + } break; case B_SIMACLONEDELETE: @@ -476,7 +491,9 @@ static uiBlock *image_viewmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "View Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Image Properties...|N", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Real-time Properties...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 13, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Paint Tool...|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + if (G.sima->image && (G.sima->flag & SI_DRAWTOOL)) { + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Paint Tool...|C", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + } uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Curves Tool...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Composite Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 81d94725a90..15caf325ec6 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -751,6 +751,9 @@ static void do_ipo_viewmenu(void *arg, int event) case 14: /* Clear Preview Range */ anim_previewrange_clear(); break; + case 15: /* AutoMerge Keyframes */ + G.sipo->flag ^= SIPO_NOTRANSKEYCULL; + break; } } @@ -772,6 +775,9 @@ static uiBlock *ipo_viewmenu(void *arg_unused) else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Keys|K", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, (G.sipo->flag & SIPO_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, + "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Zoom Out|NumPad -", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); diff --git a/source/blender/src/header_nla.c b/source/blender/src/header_nla.c index ef4b79c0537..13bbf0a3999 100644 --- a/source/blender/src/header_nla.c +++ b/source/blender/src/header_nla.c @@ -128,6 +128,9 @@ static void do_nla_viewmenu(void *arg, int event) case 9: /* Clear Preview Range */ anim_previewrange_clear(); break; + case 10: /* AutoMerge Keyframes */ + G.snla->flag ^= SNLA_NOTRANSKEYCULL; + break; } } @@ -148,6 +151,9 @@ static uiBlock *nla_viewmenu(void *arg_unused) } else { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Show Seconds|Ctrl T", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); } + + uiDefIconTextBut(block, BUTM, 1, (G.snla->flag & SNLA_NOTRANSKEYCULL)?ICON_CHECKBOX_DEHLT:ICON_CHECKBOX_HLT, + "AutoMerge Keyframes|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index cb3cfce62c3..82fcdd23c1f 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -1835,7 +1835,7 @@ static uiBlock *view3d_transformmenu(void *arg_unused) if (!G.obedit) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center New", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Center Cursor", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align to Transform Orientation", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Align to Transform Orientation|Ctrl Alt A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 21, ""); } if (BIF_snappingSupported()) @@ -5639,6 +5639,10 @@ void view3d_buttons(void) xco+= XIC; } + if (G.vd->twmode > (BIF_countTransformOrientation() - 1) + V3D_MANIP_CUSTOM) { + G.vd->twmode = 0; + } + str_menu = BIF_menustringTransformOrientation("Orientation"); uiDefButS(block, MENU, B_MAN_MODE, str_menu,xco,0,70,YIC, &G.vd->twmode, 0, 0, 0, 0, "Transform Orientation (ALT+Space)"); MEM_freeN(str_menu); @@ -5723,11 +5727,11 @@ void view3d_buttons(void) } else if(G.f & G_PARTICLEEDIT) { uiBlockBeginAlign(block); - uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode (Ctrl Tab 1)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_PATH, B_SEL_PATH, ICON_EDGESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Path edit mode"); xco+= XIC; - uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode (Ctrl Tab 2)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_POINT, B_SEL_POINT, ICON_VERTEXSEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Point select mode"); xco+= XIC; - uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode (Ctrl Tab 3)"); + uiDefIconButBitS(block, TOG, SCE_SELECT_END, B_SEL_END, ICON_FACESEL, xco,0,XIC,YIC, &G.scene->selectmode, 1.0, 0.0, 0, 0, "Tip select mode"); xco+= XIC; uiBlockEndAlign(block); if(G.vd->drawtype > OB_WIRE) { diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 7af6b67bfa3..ab8e53c3cb3 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -2114,7 +2114,7 @@ static int ui_act_as_text_but(uiBut *but) static int ui_do_but_NUM(uiBut *but) { - double value; + double value, butrange; float deler, fstart, f, tempf, pressure; int lvalue, temp, orig_x; /* , firsttime=1; */ short retval=0, qual, sx, mval[2], pos=0; @@ -2128,7 +2128,8 @@ static int ui_do_but_NUM(uiBut *but) sx= mval[0]; orig_x = sx; /* Store so we can scale the rate of change by the dist the mouse is from its original xlocation */ - fstart= (value - but->min)/(but->max-but->min); + butrange= (but->max - but->min); + fstart= (butrange == 0.0)? 0.0f: (value - but->min)/butrange; f= fstart; temp= (int)value; diff --git a/source/blender/src/interface_icons.c b/source/blender/src/interface_icons.c index 641669e2168..bd06e461745 100644 --- a/source/blender/src/interface_icons.c +++ b/source/blender/src/interface_icons.c @@ -938,8 +938,8 @@ static void icon_draw_rect(float x, float y, int w, int h, float aspect, int rw, { ui_rasterpos_safe(x, y, aspect); - if(w<1 || h<1) { - printf("what the heck!\n"); + if((w<1 || h<1) && G.f & G_DEBUG) { + printf("what the heck! - icons are %i x %i pixels?\n", w, h); } /* rect contains image in 'rendersize', we only scale if needed */ else if(rw!=w && rh!=h) { diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 6d4b399cef0..2d8b0c81175 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -1110,7 +1110,7 @@ static void poselib_preview_init_data (tPoseLib_PreviewData *pld, Object *ob, sh return; } if (pld->marker == NULL) { - if ((apply_active==0) || (pld->act->markers.first)) { + if ((apply_active==0) && (pld->act->markers.first)) { /* just use first one then... */ pld->marker= pld->act->markers.first; printf("PoseLib had no active pose\n"); diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 4576e149ed2..de523edd33f 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -311,6 +311,8 @@ static void renderwin_draw_render_info(RenderWin *rw) static void renderwin_draw(RenderWin *rw, int just_clear) { + Image *ima; + ImBuf *ibuf; float fullrect[2][2]; int set_back_mainwindow; rcti rect; @@ -340,50 +342,45 @@ static void renderwin_draw(RenderWin *rw, int just_clear) glColor3ub(0, 0, 0); glRectfv(fullrect[0], fullrect[1]); } else { - RenderResult rres; RenderSpare *rspare= render_spare; if(rspare && rspare->showspare) { - if(rspare->ibuf) { - rres.rectx= rspare->ibuf->x; - rres.recty= rspare->ibuf->y; - rres.rect32= (int *)rspare->ibuf->rect; - rres.rectf= rspare->ibuf->rect_float; - rres.rectz= rspare->ibuf->zbuf_float; - } - else - memset(&rres, 0, sizeof(rres)); + ibuf= rspare->ibuf; + } + else { + ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); + ibuf= BKE_image_get_ibuf(ima, NULL); } - else - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); - if(rres.rectf || rres.rect32) { + if(ibuf) { + if(!ibuf->rect) + IMB_rect_from_float(ibuf); glPixelZoom(rw->zoom, rw->zoom); if(rw->flags & RW_FLAGS_ALPHA) { - if(rres.rect32) { + if(ibuf->rect) { /* swap bytes, so alpha is most significant one, then just draw it as luminance int */ if(G.order==B_ENDIAN) glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); - glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_LUMINANCE, GL_UNSIGNED_INT, rres.rect32); + glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, ibuf->rect); glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); } else { - float *trectf= MEM_mallocN(rres.rectx*rres.recty*4, "temp"); + float *trectf= MEM_mallocN(ibuf->x*ibuf->y*4, "temp"); int a, b; - for(a= rres.rectx*rres.recty -1, b= 4*a+3; a>=0; a--, b-=4) - trectf[a]= rres.rectf[b]; + for(a= ibuf->x*ibuf->y -1, b= 4*a+3; a>=0; a--, b-=4) + trectf[a]= ibuf->rect_float[b]; - glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_LUMINANCE, GL_FLOAT, trectf); + glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_FLOAT, trectf); MEM_freeN(trectf); } } else { - if(rres.rect32) - glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rres.rect32); - else if(rres.rectf) - glaDrawPixelsSafe_to32(fullrect[0][0], fullrect[0][1], rres.rectx, rres.recty, rres.rectx, rres.rectf); + if(ibuf->rect) + glaDrawPixelsSafe(fullrect[0][0], fullrect[0][1], ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + else if(ibuf->rect_float) + glaDrawPixelsSafe_to32(fullrect[0][0], fullrect[0][1], ibuf->x, ibuf->y, ibuf->x, ibuf->rect_float); } glPixelZoom(1.0, 1.0); } @@ -431,22 +428,20 @@ static void renderwin_zoom(RenderWin *rw, int ZoomIn) { static void renderwin_mouse_moved(RenderWin *rw) { - RenderResult rres; + Image *ima; + ImBuf *ibuf; RenderSpare *rspare= render_spare; if(rspare && rspare->showspare) { - if(rspare->ibuf) { - rres.rectx= rspare->ibuf->x; - rres.recty= rspare->ibuf->y; - rres.rect32= (int *)rspare->ibuf->rect; - rres.rectf= rspare->ibuf->rect_float; - rres.rectz= rspare->ibuf->zbuf_float; - } - else - memset(&rres, 0, sizeof(rres)); + ibuf= rspare->ibuf; } - else - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + else { + ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); + ibuf= BKE_image_get_ibuf(ima, NULL); + } + + if(!ibuf) + return; if (rw->flags & RW_FLAGS_PIXEL_EXAMINING) { int imgco[2], ofs=0; @@ -455,19 +450,19 @@ static void renderwin_mouse_moved(RenderWin *rw) if (renderwin_win_to_image_co(rw, rw->lmouse, imgco)) { ofs= sprintf(buf, "X: %d Y: %d ", imgco[0], imgco[1]); - if (rres.rect32) { - pxl= (char*) &rres.rect32[rres.rectx*imgco[1] + imgco[0]]; + if (ibuf->rect) { + pxl= (char*) &ibuf->rect[ibuf->x*imgco[1] + imgco[0]]; ofs+= sprintf(buf+ofs, " | R: %d G: %d B: %d A: %d", pxl[0], pxl[1], pxl[2], pxl[3]); } - if (rres.rectf) { - float *pxlf= rres.rectf + 4*(rres.rectx*imgco[1] + imgco[0]); - if(!rres.rect32){ + if (ibuf->rect_float) { + float *pxlf= ibuf->rect_float + 4*(ibuf->x*imgco[1] + imgco[0]); + if(!ibuf->rect) { ofs+= sprintf(buf+ofs, " | R: %d G: %d B: %d A: %d", FTOCHAR(pxlf[0]), FTOCHAR(pxlf[1]), FTOCHAR(pxlf[2]), FTOCHAR(pxlf[3])); } ofs+= sprintf(buf+ofs, " | R: %.3f G: %.3f B: %.3f A: %.3f ", pxlf[0], pxlf[1], pxlf[2], pxlf[3]); } - if (rres.rectz) { - float *pxlz= &rres.rectz[rres.rectx*imgco[1] + imgco[0]]; + if (ibuf->zbuf_float) { + float *pxlz= &ibuf->zbuf_float[ibuf->x*imgco[1] + imgco[0]]; sprintf(buf+ofs, "| Z: %.3f", *pxlz ); } @@ -484,8 +479,8 @@ static void renderwin_mouse_moved(RenderWin *rw) rw->zoomofs[0]= rw->pan_ofs_start[0] - delta_x/rw->zoom; rw->zoomofs[1]= rw->pan_ofs_start[1] - delta_y/rw->zoom; - rw->zoomofs[0]= CLAMPIS(rw->zoomofs[0], -rres.rectx/2, rres.rectx/2); - rw->zoomofs[1]= CLAMPIS(rw->zoomofs[1], -rres.recty/2, rres.recty/2); + rw->zoomofs[0]= CLAMPIS(rw->zoomofs[0], -ibuf->x/2, ibuf->x/2); + rw->zoomofs[1]= CLAMPIS(rw->zoomofs[1], -ibuf->y/2, ibuf->y/2); renderwin_queue_redraw(rw); } @@ -497,8 +492,8 @@ static void renderwin_mouse_moved(RenderWin *rw) h-= RW_HEADERY; renderwin_win_to_ndc(rw, rw->lmouse, ndc); - rw->zoomofs[0]= -0.5*ndc[0]*(w-rres.rectx*rw->zoom)/rw->zoom; - rw->zoomofs[1]= -0.5*ndc[1]*(h-rres.recty*rw->zoom)/rw->zoom; + rw->zoomofs[0]= -0.5*ndc[0]*(w-ibuf->x*rw->zoom)/rw->zoom; + rw->zoomofs[1]= -0.5*ndc[1]*(h-ibuf->y*rw->zoom)/rw->zoom; renderwin_queue_redraw(rw); } @@ -1188,6 +1183,7 @@ static int render_store_spare(void) RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); rspare->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, 0, 0); + rspare->ibuf->dither= G.scene->r.dither_intensity; if(rres.rect32) { rspare->ibuf->rect= MEM_dupallocN(rres.rect32); @@ -1293,6 +1289,8 @@ void BIF_do_render(int anim) allqueue(REDRAWNODE, 1); allqueue(REDRAWIMAGE, 1); } + if(G.scene->r.dither_intensity != 0.0f) + BIF_redraw_render_rect(); if (slink_flag) G.f |= G_DOSCRIPTLINKS; if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_POSTRENDER); } diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 9e358d5df0c..24f4100efdb 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -438,15 +438,15 @@ void sculpt_axislock(float *co) } } -static void add_norm_if(const BrushAction *a, float out[3], float out_flip[3], const short no[3]) +static void add_norm_if(float view_vec[3], float out[3], float out_flip[3], const short no[3]) { float fno[3] = {no[0], no[1], no[2]}; Normalize(fno); - if((Inpf(((BrushAction*)a)->symm.out, fno)) < 0) { + if((Inpf(view_vec, fno)) > 0) { VecAddf(out, out, fno); - } else if (out[0]==0.0 && out[1]==0.0 && out[2]==0.0) { + } else { VecAddf(out_flip, out_flip, fno); /* out_flip is used when out is {0,0,0} */ } } @@ -465,11 +465,11 @@ void calc_area_normal(float out[3], const BrushAction *a, const float *outdir, c if(sculptmode_brush()->flag & SCULPT_BRUSH_ANCHORED) { for(; node; node = node->next) - add_norm_if(a, out, out_flip, a->orig_norms[node->Index]); + add_norm_if(((BrushAction*)a)->symm.out, out, out_flip, a->orig_norms[node->Index]); } else { for(; node; node = node->next) - add_norm_if(a, out, out_flip, me->mvert[node->Index].no); + add_norm_if(((BrushAction*)a)->symm.out, out, out_flip, me->mvert[node->Index].no); } if (out[0]==0.0 && out[1]==0.0 && out[2]==0.0) { diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index b4d3a6c3ce2..1cff92b315f 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -1454,6 +1454,7 @@ static void input_preprocess(Sequence * seq, TStripElem* se, int cfra) if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { StripCrop c; StripTransform t; + int sx,sy,dx,dy; memset(&c, 0, sizeof(StripCrop)); memset(&t, 0, sizeof(StripTransform)); @@ -1465,22 +1466,22 @@ static void input_preprocess(Sequence * seq, TStripElem* se, int cfra) t = *seq->strip->transform; } + sx = se->ibuf->x - c.left - c.right; + sy = se->ibuf->y - c.top - c.bottom; + dx = sx; + dy = sy; + + if (seq->flag & SEQ_USE_TRANSFORM) { + dx = seqrectx; + dy = seqrecty; + } + if (c.top + c.bottom >= se->ibuf->y || c.left + c.right >= se->ibuf->x || - t.xofs >= se->ibuf->x || - t.yofs >= se->ibuf->y) { + t.xofs >= dx || t.yofs >= dy) { make_black_ibuf(se->ibuf); } else { ImBuf * i; - int sx = se->ibuf->x - c.left - c.right; - int sy = se->ibuf->y - c.top - c.bottom; - int dx = sx; - int dy = sy; - - if (seq->flag & SEQ_USE_TRANSFORM) { - dx = seqrectx; - dy = seqrecty; - } if (se->ibuf->rect_float) { i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); @@ -1633,6 +1634,36 @@ static void copy_to_ibuf_still(Sequence * seq, TStripElem * se) } } +static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown) +{ + Sequence* seq_arr[MAXSEQ+1]; + int i; + TStripElem* se = 0; + + evaluate_seq_frame_gen(seq_arr, seqbasep, cfra); + + for (i = 0; i < MAXSEQ; i++) { + if (!video_seq_is_rendered(seq_arr[i])) { + continue; + } + se = give_tstripelem(seq_arr[i], cfra); + if (se) { + if (se->ibuf) { + IMB_freeImBuf(se->ibuf); + + se->ibuf= 0; + se->ok= STRIPELEM_OK; + } + + if (se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + + se->ibuf_comp = 0; + } + } + } + +} static TStripElem* do_build_seq_array_recursively( ListBase *seqbasep, int cfra, int chanshown); @@ -1683,6 +1714,10 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, use_limiter = TRUE; } } + if (meta_se) { + free_metastrip_imbufs( + &seq->seqbase, seq->start + se->nr, 0); + } if (use_limiter) { input_preprocess(seq, se, cfra); @@ -1760,6 +1795,7 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, } } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions int oldcfra = CFRA; + Sequence * oldseq = get_last_seq(); Scene *sce= seq->scene, *oldsce= G.scene; Render *re; RenderResult rres; @@ -1838,6 +1874,7 @@ static void do_build_seq_ibuf(Sequence * seq, TStripElem *se, int cfra, if((G.f & G_PLAYANIM)==0) /* bad, is set on do_render_seq */ waitcursor(0); CFRA = oldcfra; + set_last_seq(oldseq); copy_to_ibuf_still(seq, se); @@ -1962,6 +1999,10 @@ static TStripElem* do_handle_speed_effect(Sequence * seq, int cfra) se = give_tstripelem(seq, cfra); + if (!se) { + return se; + } + if (cfra_left == cfra_right || (s->flags & SEQ_SPEED_BLEND) == 0) { test_and_auto_discard_ibuf(se); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 08a073d45b2..c8daa2bcea2 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -214,7 +214,10 @@ void add_blockhandler(ScrArea *sa, short eventcode, short val) break; } } - if(a==SPACE_MAXHANDLER) printf("error; max (4) blockhandlers reached!\n"); + if(a==SPACE_MAXHANDLER) { + error("Only %i floating panels allowed", SPACE_MAXHANDLER-1); + } + } void rem_blockhandler(ScrArea *sa, short eventcode) @@ -1077,7 +1080,10 @@ void BIF_undo_menu(void) if(menu) { short event= pupmenu_col(menu, 20); MEM_freeN(menu); - if(event>0) BKE_undo_number(event); + if(event>0) { + BKE_undo_number(event); + sound_initialize_sounds(); + } } } } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 1cc4a8fd31c..94d38ee1635 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -314,7 +314,7 @@ short sbutton(char *var, short min, short max, char *str) x1=mval[0]-250; y1=mval[1]-20; - editvar = MEM_callocN(max, "sbutton"); + editvar = MEM_callocN(max+1, "sbutton"); BLI_strncpy(editvar, var, max); uiDefButC(block, TEX, 32766, str, x1+5,y1+10,225,20, editvar,(float)min,(float)max, 0, 0, ""); @@ -2298,16 +2298,21 @@ void toolbox_generic( TBitem *generic_menu ) /* Add the menu */ for (menu = generic_menu; menu->icon != -1; menu++) { - if (menu->poin) { - but=uiDefIconTextBlockBut(block, tb_makemenu, menu->poin, ICON_RIGHTARROW_THIN, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, ""); - uiButSetFlag(but, UI_MAKE_RIGHT); - - uiButSetFunc(but, store_main, (void *)+32, (void *)ypos); + if(strcmp(menu->name, "SEPR")==0) { + uiDefBut(block, SEPR, 0, "", mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 6, NULL, 0.0, 0.0, 0, 0, ""); + ypos-=6; } else { - /* TODO - add icon support */ - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, NULL, 0.0, 0.0, 0, menu->retval, ""); + if (menu->poin) { + but=uiDefIconTextBlockBut(block, tb_makemenu, menu->poin, ICON_RIGHTARROW_THIN, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, ""); + uiButSetFlag(but, UI_MAKE_RIGHT); + + uiButSetFunc(but, store_main, (void *)+32, (void *)ypos); + } else { + /* TODO - add icon support */ + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, NULL, 0.0, 0.0, 0, menu->retval, ""); + } + ypos-=20; } - ypos-=20; } uiBlockSetButmFunc(block, menu->poin, NULL); diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index 6e4641a4d12..10035c61651 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -243,6 +243,63 @@ float InputVerticalAbsolute(TransInfo *t, short mval[2]) { return Inpf(t->viewinv[1], vec) * 2.0f; } +float InputDeltaAngle(TransInfo *t, short mval[2]) +{ + double dx2 = mval[0] - t->center2d[0]; + double dy2 = mval[1] - t->center2d[1]; + double B = sqrt(dx2*dx2+dy2*dy2); + + double dx1 = t->imval[0] - t->center2d[0]; + double dy1 = t->imval[1] - t->center2d[1]; + double A = sqrt(dx1*dx1+dy1*dy1); + + double dx3 = mval[0] - t->imval[0]; + double dy3 = mval[1] - t->imval[1]; + + /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */ + double deler = ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3)) + / (2.0 * (A*B?A*B:1.0)); + /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */ + + float dphi; + + dphi = saacos((float)deler); + if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; + + /* If the angle is zero, because of lack of precision close to the 1.0 value in acos + * approximate the angle with the oposite side of the normalized triangle + * This is a good approximation here since the smallest acos value seems to be around + * 0.02 degree and lower values don't even have a 0.01% error compared to the approximation + * */ + if (dphi == 0) + { + double dx, dy; + + dx2 /= A; + dy2 /= A; + + dx1 /= B; + dy1 /= B; + + dx = dx1 - dx2; + dy = dy1 - dy2; + + dphi = sqrt(dx*dx + dy*dy); + if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; + } + + if(t->flag & T_SHIFT_MOD) dphi = dphi/30.0f; + + /* if no delta angle, don't update initial position */ + if (dphi != 0) + { + t->imval[0] = mval[0]; + t->imval[1] = mval[1]; + } + + return dphi; +} + /* ************************** SPACE DEPENDANT CODE **************************** */ void setTransformViewMatrices(TransInfo *t) @@ -2584,23 +2641,6 @@ int Rotation(TransInfo *t, short mval[2]) float final; - double dx2 = t->center2d[0] - mval[0]; - double dy2 = t->center2d[1] - mval[1]; - double B = sqrt(dx2*dx2+dy2*dy2); - - double dx1 = t->center2d[0] - t->imval[0]; - double dy1 = t->center2d[1] - t->imval[1]; - double A = sqrt(dx1*dx1+dy1*dy1); - - double dx3 = mval[0] - t->imval[0]; - double dy3 = mval[1] - t->imval[1]; - /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */ - double deler= ((double)((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3) )) - / (2.0 * (A*B?A*B:1.0)); - /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */ - - float dphi; - float axis[3]; float mat[3][3]; @@ -2608,19 +2648,7 @@ int Rotation(TransInfo *t, short mval[2]) VecMulf(axis, -1.0f); Normalize(axis); - dphi = saacos((float)deler); - if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; - - if(t->flag & T_SHIFT_MOD) t->fac += dphi/30.0f; - else t->fac += dphi; - - /* - clamping angle between -2 PI and 2 PI (not sure if useful so commented out - theeth) - if (t->fac >= 2 * M_PI) - t->fac -= 2 * M_PI; - else if (t->fac <= -2 * M_PI) - t->fac -= -2 * M_PI; - */ + t->fac += InputDeltaAngle(t, mval); final = t->fac; @@ -2628,9 +2656,6 @@ int Rotation(TransInfo *t, short mval[2]) snapGrid(t, &final); - t->imval[0] = mval[0]; - t->imval[1] = mval[1]; - if (t->con.applyRot) { t->con.applyRot(t, NULL, axis); } @@ -3097,27 +3122,7 @@ int Tilt(TransInfo *t, short mval[2]) float final; - double dx2 = t->center2d[0] - mval[0]; - double dy2 = t->center2d[1] - mval[1]; - double B = (float)sqrt(dx2*dx2+dy2*dy2); - - double dx1 = t->center2d[0] - t->imval[0]; - double dy1 = t->center2d[1] - t->imval[1]; - double A = (float)sqrt(dx1*dx1+dy1*dy1); - - double dx3 = mval[0] - t->imval[0]; - double dy3 = mval[1] - t->imval[1]; - - double deler= ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3)) - / (2 * A * B); - - float dphi; - - dphi = saacos((float)deler); - if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; - - if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f; - else t->fac += dphi; + t->fac += InputDeltaAngle(t, mval); final = t->fac; @@ -3125,9 +3130,6 @@ int Tilt(TransInfo *t, short mval[2]) snapGrid(t, &final); - t->imval[0] = mval[0]; - t->imval[1] = mval[1]; - if (hasNumInput(&t->num)) { char c[20]; @@ -3346,8 +3348,17 @@ void initBevel(TransInfo *t) { t->mode = TFM_BEVEL; t->flag |= T_NO_CONSTRAINT; + t->num.flag |= NUM_NO_NEGATIVE; t->transform = Bevel; t->handleEvent = handleEventBevel; + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + /* DON'T KNOW WHY THIS IS NEEDED */ if (G.editBMesh->imval[0] == 0 && G.editBMesh->imval[1] == 0) { /* save the initial mouse co */ G.editBMesh->imval[0] = t->imval[0]; @@ -3403,6 +3414,10 @@ int Bevel(TransInfo *t, short mval[2]) mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal"; distance = InputHorizontalAbsolute(t, mval)/4; /* 4 just seemed a nice value to me, nothing special */ + + distance = fabs(distance); + + snapGrid(t, &distance); applyNumInput(&t->num, &distance); @@ -3412,7 +3427,7 @@ int Bevel(TransInfo *t, short mval[2]) outputNumInput(&(t->num), c); - sprintf(str, "Bevel: %s", c); + sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, mode); } else { /* default header print */ @@ -3899,36 +3914,12 @@ int BoneRoll(TransInfo *t, short mval[2]) float final; - double dx2 = t->center2d[0] - mval[0]; - double dy2 = t->center2d[1] - mval[1]; - double B = sqrt(dx2*dx2+dy2*dy2); - - double dx1 = t->center2d[0] - t->imval[0]; - double dy1 = t->center2d[1] - t->imval[1]; - double A = sqrt(dx1*dx1+dy1*dy1); - - double dx3 = mval[0] - t->imval[0]; - double dy3 = mval[1] - t->imval[1]; - /* use doubles here, to make sure a "1.0" (no rotation) doesnt become 9.999999e-01, which gives 0.02 for acos */ - double deler= ((double)((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3) )) - / (2.0 * (A*B?A*B:1.0)); - /* (A*B?A*B:1.0f) this takes care of potential divide by zero errors */ - - float dphi; - - dphi = saacos((float)deler); - if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi; - - if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f; - else t->fac += dphi; + t->fac += InputDeltaAngle(t, mval); final = t->fac; snapGrid(t, &final); - t->imval[0] = mval[0]; - t->imval[1] = mval[1]; - if (hasNumInput(&t->num)) { char c[20]; diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c index 1b85962a768..769ebd2ea97 100644 --- a/source/blender/src/transform_constraints.c +++ b/source/blender/src/transform_constraints.c @@ -412,7 +412,8 @@ static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3]) VECCOPY(vec, t->con.mtx[2]); break; } - if (!(mode & CON_NOFLIP)) { + /* don't flip axis if asked to or if num input */ + if (!(mode & CON_NOFLIP) && hasNumInput(&t->num) == 0) { if (Inpf(vec, t->viewinv[2]) > 0.0f) { VecMulf(vec, -1.0f); } diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 9a9a454ef3d..f69218664ea 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -144,6 +144,8 @@ extern ListBase editelems; /* local function prototype - for Object/Bone Constraints */ static short constraints_list_needinv(TransInfo *t, ListBase *list); +/* local function prototype - for finding number of keyframes that are selected for editing */ +static int count_ipo_keys(Ipo *ipo, char side, float cfra); /* ************************** Functions *************************** */ @@ -2215,9 +2217,9 @@ static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int sele td->flag |= TD_SELECTED; td->dist= 0.0; } - else + else { td->dist= MAXFLOAT; - + } Mat3One(td->mtx); Mat3One(td->smtx); } @@ -2229,25 +2231,57 @@ static void createTransUVs(TransInfo *t) MTFace *tf; int count=0, countsel=0; int propmode = t->flag & T_PROP_EDIT; - + int efa_s1,efa_s2,efa_s3,efa_s4; + EditMesh *em = G.editMesh; EditFace *efa; if(is_uv_tface_editing_allowed()==0) return; /* count */ - for (efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (simaFaceDraw_Check(efa, tf)) { - if (simaUVSel_Check(efa, tf, 0)) countsel++; - if (simaUVSel_Check(efa, tf, 1)) countsel++; - if (simaUVSel_Check(efa, tf, 2)) countsel++; - if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++; - if(propmode) - count += (efa->v4)? 4: 3; + if (G.sima->flag & SI_BE_SQUARE && !propmode) { + for (efa= em->faces.first; efa; efa= efa->next) { + /* store face pointer for second loop, prevent second lookup */ + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if (simaFaceDraw_Check(efa, tf)) { + efa->tmp.p = tf; + + efa_s1 = simaUVSel_Check(efa, tf, 0); + efa_s2 = simaUVSel_Check(efa, tf, 1); + efa_s3 = simaUVSel_Check(efa, tf, 2); + if (efa->v4) { + efa_s4 = simaUVSel_Check(efa, tf, 3); + if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) { + countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */ + } + } else { + /* tri's are delt with normally when SI_BE_SQUARE's enabled */ + if (efa_s1) countsel++; + if (efa_s2) countsel++; + if (efa_s3) countsel++; + } + } else { + efa->tmp.p = NULL; + } + } + } else { + for (efa= em->faces.first; efa; efa= efa->next) { + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if (simaFaceDraw_Check(efa, tf)) { + efa->tmp.p = tf; + + if (simaUVSel_Check(efa, tf, 0)) countsel++; + if (simaUVSel_Check(efa, tf, 1)) countsel++; + if (simaUVSel_Check(efa, tf, 2)) countsel++; + if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++; + if(propmode) + count += (efa->v4)? 4: 3; + } else { + efa->tmp.p = NULL; + } } } - + /* note: in prop mode we need at least 1 selected */ if (countsel==0) return; @@ -2262,21 +2296,66 @@ static void createTransUVs(TransInfo *t) td= t->data; td2d= t->data2d; - for (efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (simaFaceDraw_Check(efa, tf)) { - if(propmode || simaUVSel_Check(efa, tf, 0)) - UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0)); - if(propmode || simaUVSel_Check(efa, tf, 1)) - UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1)); - if(propmode || simaUVSel_Check(efa, tf, 2)) - UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2)); + + if (G.sima->flag & SI_BE_SQUARE && !propmode) { + for (efa= em->faces.first; efa; efa= efa->next) { + tf=(MTFace *)efa->tmp.p; + if (tf) { + efa_s1 = simaUVSel_Check(efa, tf, 0); + efa_s2 = simaUVSel_Check(efa, tf, 1); + efa_s3 = simaUVSel_Check(efa, tf, 2); + + if (efa->v4) { + efa_s4 = simaUVSel_Check(efa, tf, 3); + + if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) { + /* all corners of this quad need their edges moved. so we must store TD for each */ + + UVsToTransData(td, td2d, tf->uv[0], efa_s1); + if (!efa_s1) td->flag |= TD_SKIP; + td++; td2d++; + + UVsToTransData(td, td2d, tf->uv[1], efa_s2); + if (!efa_s2) td->flag |= TD_SKIP; + td++; td2d++; + + UVsToTransData(td, td2d, tf->uv[2], efa_s3); + if (!efa_s3) td->flag |= TD_SKIP; + td++; td2d++; - if(efa->v4 && (propmode || simaUVSel_Check(efa, tf, 3))) - UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3)); + UVsToTransData(td, td2d, tf->uv[3], efa_s4); + if (!efa_s4) td->flag |= TD_SKIP; + td++; td2d++; + } + } else { + /* tri's are delt with normally when SI_BE_SQUARE's enabled */ + if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1); + if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1); + if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1); + } + } + } + } else { + for (efa= em->faces.first; efa; efa= efa->next) { + /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + if (simaFaceDraw_Check(efa, tf)) {*/ + if ((tf=(MTFace *)efa->tmp.p)) { + if (propmode) { + UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0)); + UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1)); + UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2)); + if(efa->v4) + UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3)); + } else { + if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1); + if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1); + if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1); + if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1); + } + } } } - + if (G.sima->flag & SI_LIVE_UNWRAP) unwrap_lscm_live_begin(); } @@ -2304,9 +2383,8 @@ void flushTransUVs(TransInfo *t) td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height; } } - - /* always call this, also for cancel (it transforms non-selected vertices...) */ - if((G.sima->flag & SI_BE_SQUARE)) + + if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL)) be_square_tface_uv(em); /* this is overkill if G.sima->lock is not set, but still needed */ @@ -2490,6 +2568,93 @@ static void posttrans_action_clean (bAction *act) BLI_freelistN(&act_data); } +/* Called by special_aftertrans_update to make sure selected keyframes replace + * any other keyframes which may reside on that frame (that is not selected). + * remake_all_ipos should have already been called + */ +static void posttrans_nla_clean (TransInfo *t) +{ + Base *base; + Object *ob; + bActionStrip *strip; + bActionChannel *achan; + bConstraintChannel *conchan; + float cfra; + char side; + int i; + + /* which side of the current frame should be allowed */ + if (t->mode == TFM_TIME_EXTEND) { + /* only side on which mouse is gets transformed */ + float xmouse, ymouse; + + areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse); + side = (xmouse > CFRA) ? 'R' : 'L'; + } + else { + /* normal transform - both sides of current frame are considered */ + side = 'B'; + } + + /* only affect keyframes */ + for (base=G.scene->base.first; base; base=base->next) { + ob= base->object; + + /* Check object ipos */ + i= count_ipo_keys(ob->ipo, side, CFRA); + if (i) posttrans_ipo_clean(ob->ipo); + + /* Check object constraint ipos */ + for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) { + i= count_ipo_keys(conchan->ipo, side, CFRA); + if (i) posttrans_ipo_clean(ob->ipo); + } + + /* skip actions and nlastrips if object is collapsed */ + if (ob->nlaflag & OB_NLA_COLLAPSED) + continue; + + /* Check action ipos */ + if (ob->action) { + /* exclude if strip is selected too */ + for (strip=ob->nlastrips.first; strip; strip=strip->next) { + if (strip->flag & ACTSTRIP_SELECT) { + if (strip->act == ob->action) + break; + } + } + if (strip==NULL) { + cfra = get_action_frame(ob, CFRA); + + for (achan=ob->action->chanbase.first; achan; achan=achan->next) { + if (EDITABLE_ACHAN(achan)) { + i= count_ipo_keys(achan->ipo, side, cfra); + if (i) { + actstrip_map_ipo_keys(ob, achan->ipo, 0, 1); + posttrans_ipo_clean(achan->ipo); + actstrip_map_ipo_keys(ob, achan->ipo, 1, 1); + } + + /* Check action constraint ipos */ + if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { + if (EDITABLE_CONCHAN(conchan)) { + i = count_ipo_keys(conchan->ipo, side, cfra); + if (i) { + actstrip_map_ipo_keys(ob, conchan->ipo, 0, 1); + posttrans_ipo_clean(conchan->ipo); + actstrip_map_ipo_keys(ob, conchan->ipo, 1, 1); + } + } + } + } + } + } + } + } + } +} + /* ----------------------------- */ /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ @@ -2975,6 +3140,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) ListBase fakecons = {NULL, NULL}; float obmtx[3][3]; short constinv; + short skip_invert = 0; /* axismtx has the real orientation */ Mat3CpyMat4(td->axismtx, ob->obmat); @@ -2987,8 +3153,13 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) * inverse correction to stop it from screwing up space conversion * matrix later */ - constinv= constraints_list_needinv(t, &ob->constraints); - if (ob->track || constinv==0) { + constinv = constraints_list_needinv(t, &ob->constraints); + + /* disable constraints inversion for dummy pass */ + if (t->mode == TFM_DUMMY) + skip_invert = 1; + + if (skip_invert == 0 && (ob->track || constinv==0)) { track= ob->track; ob->track= NULL; @@ -3487,8 +3658,6 @@ void special_aftertrans_update(TransInfo *t) if (key->ipo) { IpoCurve *icu; - - if ( (G.saction->flag & SACTION_NOTRANSKEYCULL)==0 && (cancelled == 0) ) { @@ -3507,17 +3676,39 @@ void special_aftertrans_update(TransInfo *t) G.saction->flag &= ~SACTION_MOVING; } else if (t->spacetype == SPACE_NLA) { + recalc_all_ipos(); // bad synchronize_action_strips(); /* cleanup */ for (base=G.scene->base.first; base; base=base->next) base->flag &= ~(BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA); - recalc_all_ipos(); // bad + /* after transform, remove duplicate keyframes on a frame that resulted from transform */ + if ( (G.snla->flag & SNLA_NOTRANSKEYCULL)==0 && + (cancelled == 0) ) + { + posttrans_nla_clean(t); + } } else if (t->spacetype == SPACE_IPO) { // FIXME! is there any code from the old transform_ipo that needs to be added back? + /* after transform, remove duplicate keyframes on a frame that resulted from transform */ + if (G.sipo->ipo) + { + if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && + (cancelled == 0) ) + { + if (NLA_IPO_SCALED) { + actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); + posttrans_ipo_clean(G.sipo->ipo); + actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1); + } + else + posttrans_ipo_clean(G.sipo->ipo); + } + } + /* resetting slow-parents isn't really necessary when editing sequence ipo's */ if (G.sipo->blocktype==ID_SEQ) resetslowpar= 0; diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index a0dde01ba8e..8154929eb17 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -972,11 +972,12 @@ void calculateCenter(TransInfo *t) calculateCenterMedian(t); break; case V3D_ACTIVE: + { /* set median, and if if if... do object center */ - + EditSelection ese; /* EDIT MODE ACTIVE EDITMODE ELEMENT */ - if (G.obedit && G.obedit->type == OB_MESH && G.editMesh->selected.last) { - EM_editselection_center(t->center, G.editMesh->selected.last); + if (G.obedit && G.obedit->type == OB_MESH && EM_get_actSelection(&ese)) { + EM_editselection_center(t->center, &ese); calculateCenter2D(t); break; } /* END EDIT MODE ACTIVE ELEMENT */ @@ -989,6 +990,8 @@ void calculateCenter(TransInfo *t) projectIntView(t, t->center, t->center2d); } } + + } } /* setting constraint center */ diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index 601d516f26f..5c06aaea890 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -230,11 +230,12 @@ int calc_manipulator_stats(ScrArea *sa) if(G.obedit->type==OB_MESH) { EditMesh *em = G.editMesh; EditVert *eve; + EditSelection ese; float vec[3]= {0,0,0}; /* USE LAST SELECTE WITH ACTIVE */ - if (G.vd->around==V3D_ACTIVE && em->selected.last) { - EM_editselection_center(vec, em->selected.last); + if (G.vd->around==V3D_ACTIVE && EM_get_actSelection(&ese)) { + EM_editselection_center(vec, &ese); calc_tw_center(vec); totsel= 1; } else { @@ -435,10 +436,10 @@ int calc_manipulator_stats(ScrArea *sa) if(G.obedit) { float mat[3][3]; int type; - + strcpy(t->spacename, "normal"); - - type = getTransformOrientation(normal, plane, 0); + + type = getTransformOrientation(normal, plane, (G.vd->around == V3D_ACTIVE)); switch (type) { diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 5c35a80c43f..6696fcf95d6 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" #include "DNA_object_types.h" @@ -44,6 +45,7 @@ #include "BLI_editVert.h" #include "BIF_editmesh.h" +#include "BIF_editarmature.h" #include "BIF_interface.h" #include "BIF_space.h" #include "BIF_toolbox.h" @@ -379,16 +381,16 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) { EditMesh *em = G.editMesh; EditVert *eve; + EditSelection ese; float vec[3]= {0,0,0}; /* USE LAST SELECTED WITH ACTIVE */ - if (activeOnly && em->selected.last) + if (activeOnly && EM_get_actSelection(&ese)) { - EditSelection *ese = em->selected.last; - EM_editselection_normal(normal, ese); - EM_editselection_plane(plane, ese); + EM_editselection_normal(normal, &ese); + EM_editselection_plane(plane, &ese); - switch (ese->type) + switch (ese.type) { case EDITVERT: result = ORIENTATION_VERT; @@ -605,6 +607,38 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) result = ORIENTATION_NORMAL; } } + else if (G.obedit->type == OB_ARMATURE) + { + bArmature *arm = G.obedit->data; + EditBone *ebone; + + for (ebone = G.edbo.first; ebone; ebone=ebone->next) { + if (arm->layer & ebone->layer) + { + if (ebone->flag & BONE_SELECTED) + { + float vec[3]; + VecSubf(vec, ebone->tail, ebone->head); + Normalize(vec); + VecAddf(normal, normal, vec); + } + } + } + + Normalize(normal); + Crossf(plane, G.obedit->obmat[0], normal); + + if (Inpf(plane, plane) < FLT_EPSILON) + { + Crossf(plane, G.obedit->obmat[1], normal); + } + + if (plane[0] != 0 || plane[1] != 0 || plane[2] != 0) + { + result = ORIENTATION_EDGE; + } + + } Mat4Mul3Vecfl(G.obedit->obmat, plane); Mat4Mul3Vecfl(G.obedit->obmat, normal); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 3ceb8aae1ae..b7029c3225b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -389,7 +389,7 @@ static void init_userdef_file(void) if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 11)) { bTheme *btheme; for (btheme= U.themes.first; btheme; btheme= btheme->next) { - /* these should all use the same colour */ + /* these should all use the same color */ SETCOL(btheme->tv3d.cframe, 0x60, 0xc0, 0x40, 255); SETCOL(btheme->tipo.cframe, 0x60, 0xc0, 0x40, 255); SETCOL(btheme->tact.cframe, 0x60, 0xc0, 0x40, 255); @@ -402,7 +402,7 @@ static void init_userdef_file(void) if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 13)) { bTheme *btheme; for (btheme= U.themes.first; btheme; btheme= btheme->next) { - /* action channel groups (recolour anyway) */ + /* action channel groups (recolor anyway) */ SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255); SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255); diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 163a116371d..2904ca60a12 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -741,7 +741,7 @@ void viewmove(int mode) // dist correction from other movement devices - if(dz_flag) { + if((dz_flag)||G.vd->dist==0) { dz_flag = 0; G.vd->dist = m_dist; upvec[0] = upvec[1] = 0; @@ -2111,7 +2111,7 @@ void smooth_view(View3D *v3d, float *ofs, float *quat, float *dist, float *lens) changed = 1; } - /* The new view is different from teh old one + /* The new view is different from the old one * so animate the view */ if (changed) { diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index a656c5e5523..ffd66655069 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -125,6 +125,22 @@ void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) } +void KX_BlenderRenderTools::SetClientObject(void* obj) +{ + if (m_clientobject != obj) + { + if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) + { + glFrontFace(GL_CCW); + } else + { + glFrontFace(GL_CW); + } + m_clientobject = obj; + m_modified = true; + } +} + bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { double* const oglmatrix = (double* const) data; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index 662f5bd9af1..31eaa14d66b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -105,6 +105,8 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); + virtual void SetClientObject(void* obj); + }; #endif //__KX_BLENDERRENDERTOOLS diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 089af9a68e7..82d16ffa181 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -87,6 +87,7 @@ #include "DNA_action_types.h" #include "BKE_main.h" #include "BKE_global.h" +#include "BKE_object.h" #include "BL_SkinMeshObject.h" #include "BL_SkinDeformer.h" #include "BL_MeshDeformer.h" @@ -1571,8 +1572,9 @@ static KX_LightObject *gamelight_from_blamp(Lamp *la, unsigned int layerflag, KX return gamelight; } -static KX_Camera *gamecamera_from_bcamera(Camera *ca, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) { - RAS_CameraData camdata(ca->lens, ca->clipsta, ca->clipend, ca->type == CAM_PERSP); +static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) { + Camera* ca = static_cast<Camera*>(ob->data); + RAS_CameraData camdata(ca->lens, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob)); KX_Camera *gamecamera; gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata); @@ -1607,7 +1609,7 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_CAMERA: { - KX_Camera* gamecamera = gamecamera_from_bcamera(static_cast<Camera*>(ob->data), kxscene, converter); + KX_Camera* gamecamera = gamecamera_from_bcamera(ob, kxscene, converter); gameobj = gamecamera; //don't add a reference: the camera list in kxscene->m_cameras is not released at the end diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index edda7657ef9..885981a2898 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -462,6 +462,22 @@ int GPC_RenderTools::applyLights(int objectlayer) } +void GPC_RenderTools::SetClientObject(void* obj) +{ + if (m_clientobject != obj) + { + if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) + { + glFrontFace(GL_CCW); + } else + { + glFrontFace(GL_CW); + } + m_clientobject = obj; + m_modified = true; + } +} + bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { double* const oglmatrix = (double* const) data; diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 9b86869af73..ee0212da643 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -153,6 +153,8 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); + virtual void SetClientObject(void* obj); + protected: /** * Copied from KX_BlenderGL.cpp in KX_blenderhook diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 09eb2053bfe..27e47d72bbe 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -204,6 +204,11 @@ float KX_Camera::GetCameraFar() const return m_camdata.m_clipend; } +float KX_Camera::GetFocalLength() const +{ + return m_camdata.m_focallength; +} + RAS_CameraData* KX_Camera::GetCameraData() diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 4cc8c049f91..75d574cd697 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -184,12 +184,14 @@ public: */ const MT_Matrix4x4& GetModelviewMatrix() const; - /** Gets the focal length. */ + /** Gets the aperture. */ float GetLens() const; /** Gets the near clip distance. */ float GetCameraNear() const; /** Gets the far clip distance. */ float GetCameraFar() const; + /** Gets the focal length (only used for stereo rendering) */ + float GetFocalLength() const; /** Gets all camera data. */ RAS_CameraData* GetCameraData(); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index fb636b23082..dada47e2fa4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -77,6 +77,7 @@ KX_GameObject::KX_GameObject( m_layer(0), m_bSuspendDynamics(false), m_bUseObjectColor(false), + m_bIsNegativeScaling(false), m_bVisible(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), @@ -335,7 +336,7 @@ double* KX_GameObject::GetOpenGLMatrix() trans.setBasis(GetSGNode()->GetWorldOrientation()); MT_Vector3 scaling = GetSGNode()->GetWorldScaling(); - + m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false; trans.scale(scaling[0], scaling[1], scaling[2]); trans.getValue(fl); @@ -743,6 +744,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS}, KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE(KX_GameObject, rayCastTo), + KX_PYMETHODTABLE(KX_GameObject, rayCast), {NULL,NULL} //Sentinel }; @@ -1325,7 +1327,7 @@ bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT } KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, -"rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that match prop\n" +"rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n" " prop = property name that object must have; can be omitted => detect any object\n" " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n" " other = 3-tuple or object reference") @@ -1380,6 +1382,89 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, Py_Return; } +KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, +"rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n" +" prop = property name that object must have; can be omitted => detect any object\n" +" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" +" from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" +" Can None or omitted => start from self object center\n" +" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" +"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") +{ + MT_Point3 toPoint; + MT_Point3 fromPoint; + PyObject* pyto; + PyObject* pyfrom = NULL; + float dist = 0.0f; + char *propName = NULL; + KX_GameObject *other; + + if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) + return NULL; + + if (!PyVecTo(pyto, toPoint)) + { + PyErr_Clear(); + if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type)) + return NULL; + other = static_cast<KX_GameObject*>(pyto); + toPoint = other->NodeGetWorldPosition(); + } + if (!pyfrom || pyfrom == Py_None) + { + fromPoint = NodeGetWorldPosition(); + } + else if (!PyVecTo(pyfrom, fromPoint)) + { + PyErr_Clear(); + if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type)) + return NULL; + other = static_cast<KX_GameObject*>(pyfrom); + fromPoint = other->NodeGetWorldPosition(); + } + + if (dist != 0.0f) + { + MT_Vector3 toDir = toPoint-fromPoint; + toDir.normalize(); + toPoint = fromPoint + (dist) * toDir; + } + + MT_Point3 resultPoint; + MT_Vector3 resultNormal; + PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); + KX_IPhysicsController *spc = GetPhysicsController(); + KX_GameObject *parent = GetParent(); + if (!spc && parent) + spc = parent->GetPhysicsController(); + if (parent) + parent->Release(); + + m_pHitObject = NULL; + if (propName) + m_testPropName = propName; + else + m_testPropName.SetLength(0); + KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this)); + + if (m_pHitObject) + { + PyObject* returnValue = PyTuple_New(3); + if (!returnValue) + return NULL; + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + return returnValue; + //return Py_BuildValue("(O,(fff),(fff))", + // m_pHitObject->AddRef(), // trick: KX_GameObject are not true Python object, they use a difference reference count system + // resultPoint[0], resultPoint[1], resultPoint[2], + // resultNormal[0], resultNormal[1], resultNormal[2]); + } + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //Py_Return; +} + /* --------------------------------------------------------------------- * Some stuff taken from the header * --------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index b83d63e26bf..3758651f53d 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -75,6 +75,7 @@ protected: bool m_bSuspendDynamics; bool m_bUseObjectColor; + bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; // Is this object set to be visible? Only useful for the @@ -368,7 +369,15 @@ public: { return m_bDyna; } - + + /** + * Check if this object has a vertex parent relationship + */ + bool IsVertexParent( ) + { + return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent()); + } + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); @@ -591,6 +600,14 @@ public: ); /** + * Get the negative scaling state + */ + bool + IsNegativeScaling( + void + ) { return m_bIsNegativeScaling; } + + /** * @section Logic bubbling methods. */ @@ -657,6 +674,7 @@ public: KX_PYMETHOD(KX_GameObject,RemoveParent); KX_PYMETHOD(KX_GameObject,GetPhysicsId); KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); + KX_PYMETHOD_DOC(KX_GameObject,rayCast); KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); private : diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index c098f37efa8..1e3393d59a8 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -890,7 +890,7 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { - float left, right, bottom, top, nearfrust, farfrust; + float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; // KX_Camera* cam = scene->GetActiveCamera(); @@ -913,6 +913,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) float lens = cam->GetLens(); nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); + focallength = cam->GetFocalLength(); if (!cam->GetCameraData()->m_perspective) { @@ -939,7 +940,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) farfrust = frustum.camfar; MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - left, right, bottom, top, nearfrust, farfrust); + left, right, bottom, top, nearfrust, farfrust, focallength); cam->SetProjectionMatrix(projmat); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 3ae09c01270..7decc5bc769 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -223,7 +223,7 @@ char KX_LightObject::doc[] = "Module KX_LightObject\n\n" "\t\tThe effect radius of the light.\n" "\tcolour -> list [r, g, b].\n" "\tcolor -> list [r, g, b].\n" -"\t\tThe colour of the light.\n" +"\t\tThe color of the light.\n" "\tlin_attenuation -> float.\n" "\t\tThe attenuation factor for the light.\n" "\tspotsize -> float.\n" diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h index d83fb79ee25..e53af22408e 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.h +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.h @@ -129,6 +129,12 @@ public : ~KX_VertexParentRelation( ); + bool + IsVertexRelation( + ) { + return true; + } + private : KX_VertexParentRelation( diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 58b87367258..b9792303565 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -69,13 +69,19 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, m_upflag = upflag; m_parentobj = 0; - if (m_object){ + if (m_object) m_object->RegisterActuator(this); - KX_GameObject* curobj = (KX_GameObject*) GetParent(); - m_parentobj = curobj->GetParent(); // check if the object is parented - if (m_parentobj) { // if so, store the initial local rotation - m_parentlocalmat = m_parentobj->GetSGNode()->GetLocalOrientation(); + if (gameobj->isA(&KX_GameObject::Type)) + { + // if the object is vertex parented, don't check parent orientation as the link is broken + if (!((KX_GameObject*)gameobj)->IsVertexParent()){ + m_parentobj = ((KX_GameObject*)gameobj)->GetParent(); // check if the object is parented + if (m_parentobj) { + // if so, store the initial local rotation + // this is needed to revert the effect of the parent inverse node (TBC) + m_parentlocalmat = m_parentobj->GetSGNode()->GetLocalOrientation(); + } } } @@ -180,6 +186,8 @@ KX_TrackToActuator::~KX_TrackToActuator() { if (m_object) m_object->UnregisterActuator(this); + if (m_parentobj) + m_parentobj->Release(); } /* end of destructor */ void KX_TrackToActuator::ProcessReplica() diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 8ef82b4943b..fbd896a55d1 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -174,9 +174,10 @@ class KX_GameObject: The ray is always casted from the center of the object, ignoring the object itself. The ray is casted towards the center of another object or an explicit [x,y,z] point. + Use rayCast() if you need to retrieve the hit point @param other: [x,y,z] or object towards which the ray is casted - @type other: L{KX_GameObject} or string + @type other: L{KX_GameObject} or 3-tuple @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other @type dist: float @param prop: property name that object must have; can be omitted => detect any object @@ -184,4 +185,32 @@ class KX_GameObject: @rtype: L{KX_GameObject} @return: the first object hit or None if no object or object does not match prop """ + def rayCast(to,from,dist,prop): + """ + Look from a point/object to another point/object and find first object hit within dist that matches prop. + Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. + Ex: + # shoot along the axis gun-gunAim (gunAim should be collision-free) + ob,point,normal = gun.rayCast(gunAim,None,50) + if ob: + # hit something + + Notes: + The ray ignores the object on which the method is called. + If is casted from/to object center or explicit [x,y,z] points. + The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray + If a property was specified and the first object hit does not have that property, there is no hit + The ray ignores collision-free objects + + @param to: [x,y,z] or object to which the ray is casted + @type to: L{KX_GameObject} or 3-tuple + @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type from: L{KX_GameObject} or 3-tuple or None + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to + @type dist: float + @param prop: property name that object must have; can be omitted => detect any object + @type prop: string + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + @return: (object,hitpoint,hitnormal) or (None,None,None) + """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/Makefile b/source/gameengine/PyDoc/Makefile deleted file mode 100644 index 7861894ddec..00000000000 --- a/source/gameengine/PyDoc/Makefile +++ /dev/null @@ -1,13 +0,0 @@ - - -SOURCES=$(shell ls *.py) -TARGETS:=$(SOURCES:.py=.html) -PYDOC=/usr/lib/python2.2/pydoc.py - -all: $(SOURCES) - epydoc -o BPY_GE_236 --url "http://www.blender.org" -t GameLogic.py \ - -n "Blender GameEngine" --no-private --no-frames \ - $(shell ls *.py ) - -clean: - rm *.html diff --git a/source/gameengine/PyDoc/epy_docgen.sh b/source/gameengine/PyDoc/epy_docgen.sh new file mode 100644 index 00000000000..7fb5e49c996 --- /dev/null +++ b/source/gameengine/PyDoc/epy_docgen.sh @@ -0,0 +1,11 @@ +# epy_docgen.sh +# generates blender python doc using epydoc +# requires epydoc in your PATH. +# run from the doc directory containing the .py files +# usage: sh epy_docgen.sh + +# set posix locale so regex works properly for [A-Z]*.py +LC_ALL=POSIX + +epydoc -v -o BPY_GE --url "http://www.blender.org" --top GameLogic \ + --name "Blender GameEngine" --no-private --no-frames *.py diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 99c0c412cf7..6aa9b34962b 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -40,13 +40,16 @@ struct RAS_CameraData int m_viewportbottom; int m_viewportright; int m_viewporttop; + float m_focallength; RAS_CameraData(float lens = 35., float clipstart = 0.1, float clipend = 100., bool perspective = true, - bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : + float focallength = 0.0f, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, + int viewportright = 0, int viewporttop = 0) : m_lens(lens), m_clipstart(clipstart), m_clipend(clipend), m_perspective(perspective), + m_focallength(focallength), m_viewport(viewport), m_viewportleft(viewportleft), m_viewportbottom(viewportbottom), diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 5e8b5ad8276..18a7f261c94 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -344,6 +344,7 @@ public: float top, float frustnear, float frustfar, + float focallength = 0.0f, bool perspective = true )=0; /** diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 16e15653c82..bcbf907741b 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -146,6 +146,7 @@ public: int layer )=0; + virtual void SetClientObject( void* obj diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 02e84f8a243..96ce220ae4d 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -325,6 +325,8 @@ void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode); } + // to reset the eventual GL_CW mode + rendertools->SetClientObject(NULL); } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index ea41b2f7d13..f99121e5b7c 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -1802,6 +1802,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( float top, float frustnear, float frustfar, + float focallength, bool ){ MT_Matrix4x4 result; @@ -1813,9 +1814,10 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( float near_div_focallength; // next 2 params should be specified on command line and in Blender publisher if (!m_setfocallength) - m_focallength = 1.5 * right; // derived from example + m_focallength = (focallength == 0.f) ? 1.5 * right // derived from example + : focallength; if (!m_seteyesep) - m_eyeseparation = 0.18 * right; // just a guess... + m_eyeseparation = m_focallength/30; // reasonable value... near_div_focallength = frustnear / m_focallength; switch(m_curreye) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index c63a7b80b7c..23714a12151 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -246,6 +246,7 @@ public: float top, float frustnear, float frustfar, + float focallength, bool perspective ); diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp index 73e16863173..ff9a9f7f371 100644 --- a/source/gameengine/SceneGraph/SG_Node.cpp +++ b/source/gameengine/SceneGraph/SG_Node.cpp @@ -148,6 +148,16 @@ GetRootSGParent( return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this); } + bool +SG_Node:: +IsVertexParent() +{ + if (m_parent_relation) + { + return m_parent_relation->IsVertexRelation(); + } + return false; +} void SG_Node:: diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h index 4808f6f7d94..5cf24de68f3 100644 --- a/source/gameengine/SceneGraph/SG_Node.h +++ b/source/gameengine/SceneGraph/SG_Node.h @@ -152,6 +152,14 @@ public: ) ; + /** + * Return vertex parent status. + */ + + bool + IsVertexParent( + ) ; + /** * Update the spatial data of this node. Iterate through * the children of this node and update their world data. diff --git a/source/gameengine/SceneGraph/SG_ParentRelation.h b/source/gameengine/SceneGraph/SG_ParentRelation.h index 1d211a9f39f..9d360d1c274 100644 --- a/source/gameengine/SceneGraph/SG_ParentRelation.h +++ b/source/gameengine/SceneGraph/SG_ParentRelation.h @@ -90,6 +90,15 @@ public : NewCopy( ) = 0; + /** + * Vertex Parent Relation are special: they don't propagate rotation + */ + virtual + bool + IsVertexRelation( + ) { + return false; + } protected : /** |