diff options
Diffstat (limited to 'source/blender')
54 files changed, 1361 insertions, 885 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 99c421c0c24..72e80301132 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -153,9 +153,9 @@ int CustomData_number_of_layers(const struct CustomData *data, int type); /* duplicate data of a layer with flag NOFREE, and remove that flag. * returns the layer data */ -void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type); +void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem); void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, - int type, const char *name); + const int type, const char *name, const int totelem); int CustomData_is_referenced_layer(struct CustomData *data, int type); /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 140f596f78c..3ab52a7c17b 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -218,7 +218,7 @@ static CCGAllocatorIFC *_getStandardAllocatorIFC(void) { /***/ -static int VertDataEqual(float *a, float *b) { +static int VertDataEqual(const float *a, const float *b) { return a[0]==b[0] && a[1]==b[1] && a[2]==b[2]; } #define VertDataZero(av) { float *_a = (float*) av; _a[0] = _a[1] = _a[2] = 0.0f; } @@ -238,7 +238,7 @@ static int VertDataEqual(float *a, float *b) { #define NormAdd(av, bv) { float *_a = (float*) av, *_b = (float*) bv; _a[0]+=_b[0]; _a[1]+=_b[1]; _a[2]+=_b[2]; } -static int _edge_isBoundary(CCGEdge *e); +static int _edge_isBoundary(const CCGEdge *e); /***/ @@ -392,7 +392,7 @@ static void _vert_addFace(CCGVert *v, CCGFace *f, CCGSubSurf *ss) { v->faces = CCGSUBSURF_realloc(ss, v->faces, (v->numFaces+1)*sizeof(*v->faces), v->numFaces*sizeof(*v->faces)); v->faces[v->numFaces++] = f; } -static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) { +static CCGEdge *_vert_findEdgeTo(const CCGVert *v, const CCGVert *vQ) { int i; for (i=0; i<v->numEdges; i++) { CCGEdge *e = v->edges[v->numEdges-1-i]; // XXX, note reverse @@ -402,7 +402,7 @@ static CCGEdge *_vert_findEdgeTo(CCGVert *v, CCGVert *vQ) { } return NULL; } -static int _vert_isBoundary(CCGVert *v) { +static int _vert_isBoundary(const CCGVert *v) { int i; for (i=0; i<v->numEdges; i++) if (_edge_isBoundary(v->edges[i])) @@ -423,7 +423,7 @@ static void _vert_free(CCGVert *v, CCGSubSurf *ss) { CCGSUBSURF_free(ss, v); } -static int VERT_seam(CCGVert *v) { +static int VERT_seam(const CCGVert *v) { return ((v->flags & Vert_eSeam) != 0); } @@ -462,7 +462,7 @@ static void _edge_addFace(CCGEdge *e, CCGFace *f, CCGSubSurf *ss) { e->faces = CCGSUBSURF_realloc(ss, e->faces, (e->numFaces+1)*sizeof(*e->faces), e->numFaces*sizeof(*e->faces)); e->faces[e->numFaces++] = f; } -static int _edge_isBoundary(CCGEdge *e) { +static int _edge_isBoundary(const CCGEdge *e) { return e->numFaces<2; } @@ -900,7 +900,7 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) { return eCCGError_None; } -CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) { +CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r) { void **prevp; CCGVert *v = NULL; short seamflag = (seam)? Vert_eSeam: 0; @@ -2484,13 +2484,13 @@ CCGError ccgSubSurf_updateLevels(CCGSubSurf *ss, int lvl, CCGFace **effectedF, i /*** External API accessor functions ***/ -int ccgSubSurf_getNumVerts(CCGSubSurf *ss) { +int ccgSubSurf_getNumVerts(const CCGSubSurf *ss) { return ss->vMap->numEntries; } -int ccgSubSurf_getNumEdges(CCGSubSurf *ss) { +int ccgSubSurf_getNumEdges(const CCGSubSurf *ss) { return ss->eMap->numEntries; } -int ccgSubSurf_getNumFaces(CCGSubSurf *ss) { +int ccgSubSurf_getNumFaces(const CCGSubSurf *ss) { return ss->fMap->numEntries; } @@ -2504,23 +2504,23 @@ CCGFace *ccgSubSurf_getFace(CCGSubSurf *ss, CCGFaceHDL f) { return (CCGFace*) _ehash_lookup(ss->fMap, f); } -int ccgSubSurf_getSubdivisionLevels(CCGSubSurf *ss) { +int ccgSubSurf_getSubdivisionLevels(const CCGSubSurf *ss) { return ss->subdivLevels; } -int ccgSubSurf_getEdgeSize(CCGSubSurf *ss) { +int ccgSubSurf_getEdgeSize(const CCGSubSurf *ss) { return ccgSubSurf_getEdgeLevelSize(ss, ss->subdivLevels); } -int ccgSubSurf_getEdgeLevelSize(CCGSubSurf *ss, int level) { +int ccgSubSurf_getEdgeLevelSize(const CCGSubSurf *ss, int level) { if (level<1 || level>ss->subdivLevels) { return -1; } else { return 1 + (1<<level); } } -int ccgSubSurf_getGridSize(CCGSubSurf *ss) { +int ccgSubSurf_getGridSize(const CCGSubSurf *ss) { return ccgSubSurf_getGridLevelSize(ss, ss->subdivLevels); } -int ccgSubSurf_getGridLevelSize(CCGSubSurf *ss, int level) { +int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level) { if (level<1 || level>ss->subdivLevels) { return -1; } else { @@ -2736,19 +2736,19 @@ void ccgFaceIterator_free(CCGFaceIterator *vi) { /*** Extern API final vert/edge/face interface ***/ -int ccgSubSurf_getNumFinalVerts(CCGSubSurf *ss) { +int ccgSubSurf_getNumFinalVerts(const CCGSubSurf *ss) { int edgeSize = 1 + (1<<ss->subdivLevels); int gridSize = 1 + (1<<(ss->subdivLevels-1)); int numFinalVerts = ss->vMap->numEntries + ss->eMap->numEntries*(edgeSize-2) + ss->fMap->numEntries + ss->numGrids*((gridSize-2) + ((gridSize-2)*(gridSize-2))); return numFinalVerts; } -int ccgSubSurf_getNumFinalEdges(CCGSubSurf *ss) { +int ccgSubSurf_getNumFinalEdges(const CCGSubSurf *ss) { int edgeSize = 1 + (1<<ss->subdivLevels); int gridSize = 1 + (1<<(ss->subdivLevels-1)); int numFinalEdges = ss->eMap->numEntries*(edgeSize-1) + ss->numGrids*((gridSize-1) + 2*((gridSize-2)*(gridSize-1))); return numFinalEdges; } -int ccgSubSurf_getNumFinalFaces(CCGSubSurf *ss) { +int ccgSubSurf_getNumFinalFaces(const CCGSubSurf *ss) { int gridSize = 1 + (1<<(ss->subdivLevels-1)); int numFinalFaces = ss->numGrids*((gridSize-1)*(gridSize-1)); return numFinalFaces; diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index 457ad2af353..543411f26f4 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -56,7 +56,7 @@ CCGError ccgSubSurf_sync (CCGSubSurf *ss); CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss); CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss); -CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r); +CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, const void *vertData, int seam, CCGVert **v_r); CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r); CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r); @@ -84,15 +84,15 @@ CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, i /***/ -int ccgSubSurf_getNumVerts (CCGSubSurf *ss); -int ccgSubSurf_getNumEdges (CCGSubSurf *ss); -int ccgSubSurf_getNumFaces (CCGSubSurf *ss); +int ccgSubSurf_getNumVerts (const CCGSubSurf *ss); +int ccgSubSurf_getNumEdges (const CCGSubSurf *ss); +int ccgSubSurf_getNumFaces (const CCGSubSurf *ss); -int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss); -int ccgSubSurf_getEdgeSize (CCGSubSurf *ss); -int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level); -int ccgSubSurf_getGridSize (CCGSubSurf *ss); -int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level); +int ccgSubSurf_getSubdivisionLevels (const CCGSubSurf *ss); +int ccgSubSurf_getEdgeSize (const CCGSubSurf *ss); +int ccgSubSurf_getEdgeLevelSize (const CCGSubSurf *ss, int level); +int ccgSubSurf_getGridSize (const CCGSubSurf *ss); +int ccgSubSurf_getGridLevelSize (const CCGSubSurf *ss, int level); CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v); CCGVertHDL ccgSubSurf_getVertVertHandle (CCGVert *v); @@ -135,9 +135,9 @@ void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridInde void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y); -int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss); -int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss); -int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss); +int ccgSubSurf_getNumFinalVerts (const CCGSubSurf *ss); +int ccgSubSurf_getNumFinalEdges (const CCGSubSurf *ss); +int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss); /***/ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 768e18b9871..98465dafecb 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -883,67 +883,71 @@ enum { CALC_WP_AUTO_NORMALIZE= (1<<1) }; +void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input) +{ + float colf[4]; + + if(coba) do_colorband(coba, input, colf); + else weight_to_rgb(colf, input); + + r_col[3] = (unsigned char)(colf[0] * 255.0f); + r_col[2] = (unsigned char)(colf[1] * 255.0f); + r_col[1] = (unsigned char)(colf[2] * 255.0f); + r_col[0] = 255; +} + + static void calc_weightpaint_vert_color( - Object *ob, const int defbase_tot, ColorBand *coba, int vert, unsigned char *col, - const char *dg_flags, int selected, int UNUSED(unselected), const int draw_flag) + unsigned char r_col[4], + MDeformVert *dv, ColorBand *coba, + const int defbase_tot, const int defbase_act, + const char *dg_flags, + const int selected, const int draw_flag) { - Mesh *me = ob->data; float input = 0.0f; int make_black= FALSE; - if (me->dvert) { - MDeformVert *dvert= &me->dvert[vert]; - - if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { - int was_a_nonzero= FALSE; - int i; - - MDeformWeight *dw= dvert->dw; - for (i = dvert->totweight; i > 0; i--, dw++) { - /* in multipaint, get the average if auto normalize is inactive - * get the sum if it is active */ - if (dw->def_nr < defbase_tot) { - if (dg_flags[dw->def_nr]) { - if (dw->weight) { - input += dw->weight; - was_a_nonzero= TRUE; - } + if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { + int was_a_nonzero= FALSE; + int i; + + MDeformWeight *dw= dv->dw; + for (i = dv->totweight; i > 0; i--, dw++) { + /* in multipaint, get the average if auto normalize is inactive + * get the sum if it is active */ + if (dw->def_nr < defbase_tot) { + if (dg_flags[dw->def_nr]) { + if (dw->weight) { + input += dw->weight; + was_a_nonzero= TRUE; } } } + } - /* make it black if the selected groups have no weight on a vertex */ - if (was_a_nonzero == FALSE) { - make_black = TRUE; - } - else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { - input /= selected; /* get the average */ - } + /* make it black if the selected groups have no weight on a vertex */ + if (was_a_nonzero == FALSE) { + make_black = TRUE; } - else { - /* default, non tricky behavior */ - input= defvert_find_weight(dvert, ob->actdef-1); + else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { + input /= selected; /* get the average */ } } - - if (make_black) { - col[3] = 0; - col[2] = 0; - col[1] = 0; - col[0] = 255; + else { + /* default, non tricky behavior */ + input= defvert_find_weight(dv, defbase_act); + } + + if (make_black) { /* TODO, theme color */ + r_col[3] = 0; + r_col[2] = 0; + r_col[1] = 0; + r_col[0] = 255; } else { - float colf[4]; CLAMP(input, 0.0f, 1.0f); - - if(coba) do_colorband(coba, input, colf); - else weight_to_rgb(colf, input); - - col[3] = (unsigned char)(colf[0] * 255.0f); - col[2] = (unsigned char)(colf[1] * 255.0f); - col[1] = (unsigned char)(colf[2] * 255.0f); - col[0] = 255; + weightpaint_color(r_col, coba, input); } } @@ -956,7 +960,7 @@ void vDM_ColorBand_store(ColorBand *coba) static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) { - // Mesh *me = ob->data; // UNUSED + Mesh *me = ob->data; MFace *mf = dm->getTessFaceArray(dm); MLoop *mloop = dm->getLoopArray(dm), *ml; MPoly *mp = dm->getPolyArray(dm); @@ -968,21 +972,32 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX); int defbase_tot = BLI_countlist(&ob->defbase); - char *defbase_sel = MEM_mallocN(defbase_tot * sizeof(char), __func__); - int selected = get_selected_defgroups(ob, defbase_sel, defbase_tot); - int unselected = defbase_tot - selected; + const int defbase_act = ob->actdef-1; + char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__); + int selected = get_selected_defgroups(ob, dg_flags, defbase_tot); wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap"); - - /*first add colors to the tesselation faces*/ - memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4); - for (i=0; i<totface; i++, mf++) { - /*origindex being NULL means we're operating on original mesh data*/ - calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag); - calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag); - calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag); - if (mf->v4) - calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag); + + if (me->dvert) { + MDeformVert *dvert= me->dvert; + /*first add colors to the tesselation faces*/ + memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4); + for (i=0; i<totface; i++, mf++) { + /*origindex being NULL means we're operating on original mesh data*/ + unsigned int fidx= mf->v4 ? 3:2; + do { + calc_weightpaint_vert_color(&wtcol[(i*4 + fidx)*4], + &dvert[*(&mf->v1 + fidx)], coba, + defbase_tot, defbase_act, + dg_flags, selected, draw_flag); + } while (fidx--); + } + } + else { + /* no weights, fill in zero */ + int col_i; + weightpaint_color((unsigned char *)&col_i, coba, 0.0f); + fill_vn_i((int *)wtcol, totface*4, col_i); } CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface); @@ -990,17 +1005,21 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) /*now add to loops, so the data can be passed through the modifier stack*/ totloop = 0; for (i=0; i<dm->numPolyData; i++, mp++) { + MDeformVert *dvert= me->dvert; + ml = mloop + mp->loopstart; for (j=0; j<mp->totloop; j++, ml++, totloop++) { BLI_array_growone(wlcol); - calc_weightpaint_vert_color(ob, defbase_tot, coba, origIndex ? origIndex[ml->v] : ml->v, - (unsigned char *)&wlcol[totloop], defbase_sel, selected, unselected, draw_flag); + calc_weightpaint_vert_color((unsigned char *)&wlcol[totloop], + &dvert[origIndex ? origIndex[ml->v] : ml->v], coba, + defbase_tot, defbase_act, + dg_flags, selected, draw_flag); } } - MEM_freeN(defbase_sel); + MEM_freeN(dg_flags); CustomData_add_layer(&dm->loopData, CD_WEIGHT_MLOOPCOL, CD_ASSIGN, wlcol, totloop); } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 69758ad66a7..f765be4bf17 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -693,7 +693,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, float *nors= dm->getTessFaceDataArray(dm, CD_NORMAL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i, j, orig, *index = DM_get_tessface_data_layer(dm, CD_ORIGINDEX); - int startFace = 0, lastFlag = 0xdeadbeef; + int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */; MCol *mcol = dm->getTessFaceDataArray(dm, CD_WEIGHT_MCOL); if(!mcol) mcol = dm->getTessFaceDataArray(dm, CD_MCOL); @@ -812,7 +812,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, int next_actualFace= dm->drawObject->triangle_to_mface[0]; glShadeModel( GL_SMOOTH ); - lastFlag = 0; + /* lastFlag = 0; */ /* UNUSED */ for(i = 0; i < tottri; i++) { int actualFace = next_actualFace; int flag = 1; @@ -2204,7 +2204,7 @@ void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3]) int i; /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); + vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); cddm->mvert = vert; for(i = 0; i < dm->numVertData; ++i, ++vert) @@ -2218,7 +2218,7 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3]) int i; /* this will just return the pointer if it wasn't a referenced layer */ - vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); + vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); cddm->mvert = vert; for(i = 0; i < dm->numVertData; ++i, ++vert) @@ -2241,7 +2241,7 @@ void CDDM_calc_normals(DerivedMesh *dm) * need to take care of the side effects here - campbell */ #if 0 /* we don't want to overwrite any referenced layers */ - cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); + cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData); #endif if (dm->numTessFaceData == 0) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f06d62da007..4e84a3a170c 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1701,7 +1701,7 @@ int CustomData_number_of_layers(const CustomData *data, int type) return number; } -void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) +void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem) { CustomDataLayer *layer; int layer_index; @@ -1713,7 +1713,20 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) layer = &data->layers[layer_index]; if (layer->flag & CD_FLAG_NOFREE) { - layer->data = MEM_dupallocN(layer->data); + /* MEM_dupallocN won’t work in case of complex layers, like e.g. + * CD_MDEFORMVERT, which has pointers to allocated data... + * So in case a custom copy function is defined, use it! + */ + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); + + if(typeInfo->copy) { + char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer"); + typeInfo->copy(layer->data, dest_data, totelem); + layer->data = dest_data; + } + else + layer->data = MEM_dupallocN(layer->data); + layer->flag &= ~CD_FLAG_NOFREE; } @@ -1721,7 +1734,7 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type) } void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, - int type, const char *name) + const int type, const char *name, const int totelem) { CustomDataLayer *layer; int layer_index; @@ -1733,7 +1746,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, layer = &data->layers[layer_index]; if (layer->flag & CD_FLAG_NOFREE) { - layer->data = MEM_dupallocN(layer->data); + /* MEM_dupallocN won’t work in case of complex layers, like e.g. + * CD_MDEFORMVERT, which has pointers to allocated data... + * So in case a custom copy function is defined, use it! + */ + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); + + if(typeInfo->copy) { + char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer"); + typeInfo->copy(layer->data, dest_data, totelem); + layer->data = dest_data; + } + else + layer->data = MEM_dupallocN(layer->data); + layer->flag &= ~CD_FLAG_NOFREE; } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 5e10fbb70c0..d848185cd07 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -216,7 +216,7 @@ void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) dvert->dw[0].weight= 1.0f; } else { - MDeformWeight *dw_lock; + MDeformWeight *dw_lock = NULL; MDeformWeight *dw; unsigned int i; float tot_weight= 0.0f; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index c7a2a3752e9..0c5d5f238ff 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -3214,7 +3214,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, /* hit data */ float hitCoord[3]; int hitFace = -1; - short hitQuad; + short hitQuad = 0; /* Supersampling factor */ if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) @@ -4641,7 +4641,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc #pragma omp parallel for schedule(static) for (index=0; index<sData->total_points; index++) { - float prev_point[3]; + float prev_point[3] = {0.0f, 0.0f, 0.0f}; if (do_velocity_data && !new_bdata) { copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v); } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index cedb1390799..421764f7191 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -231,6 +231,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, BLI_array_declare(fverts); EdgeHash *ehash; float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss); + float uv[3]= {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0]= limit[1]= STD_UV_CONNECT_LIMIT; vmap= make_uv_vert_map(mpoly, mloop, mloopuv, totface, totvert, 0, limit); @@ -254,11 +255,8 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, if (v->separate) { CCGVert *ssv; CCGVertHDL vhdl = SET_INT_IN_POINTER(v->f*4 + v->tfindex); - float uv[3]; - uv[0]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[0]; - uv[1]= mloopuv[mpoly[v->f].loopstart + v->tfindex].uv[1]; - uv[2]= 0.0f; + copy_v2_v2(uv, mloopuv[mpoly[v->f].loopstart + v->tfindex].uv); ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv); } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 828ecb2d535..83adfa12236 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1154,7 +1154,7 @@ int BKE_tracking_next(MovieTrackingContext *context) #pragma omp parallel for private(a) shared(ibuf_new, ok) if(map_size>1) for(a= 0; a<map_size; a++) { - TrackContext *track_context; + TrackContext *track_context = NULL; MovieTrackingTrack *track; MovieTrackingMarker *marker; diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 059a167d073..c2cb4582280 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -199,6 +199,7 @@ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int s float normalize_vn_vn(float *array_tar, const float *array_src, const int size); float normalize_vn(float *array_tar, const int size); void range_vn_i(int *array_tar, const int size, const int start); +void range_vn_fl(float *array_tar, const int size, const float start, const float step); void negate_vn(float *array_tar, const int size); void negate_vn_vn(float *array_tar, const float *array_src, const int size); void mul_vn_fl(float *array_tar, const int size, const float f); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index a6b4f2c9b92..94189af34fa 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -279,24 +279,22 @@ # endif # if defined(__GNUC__) || defined(_MSC_VER) /* check __func__ is available */ # define BLI_assert(a) \ -do { \ - if (!(a)) { \ + (void)((!(a)) ? ( \ + ( \ fprintf(stderr, \ "BLI_assert failed: %s, %s(), %d at \'%s\'\n", \ - __FILE__, __func__, __LINE__, STRINGIFY(a)); \ - _dummy_abort(); \ - } \ -} while (0) + __FILE__, __func__, __LINE__, STRINGIFY(a)), \ + _dummy_abort(), \ + NULL)) : NULL) # else -# define BLI_assert(a) \ -do { \ - if (0 == (a)) { \ +# define BLI_assert(a) \ + (void)((!(a)) ? ( \ + ( \ fprintf(stderr, \ "BLI_assert failed: %s, %d at \'%s\'\n", \ - __FILE__, __LINE__, STRINGIFY(a)); \ - _dummy_abort(); \ - } \ -} while (0) + __FILE__, __LINE__, STRINGIFY(a)), \ + _dummy_abort(), \ + NULL)) : NULL) # endif #else # define BLI_assert(a) (void)0 diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c index 140e1752648..861efcfe6c5 100644 --- a/source/blender/blenlib/intern/bpath.c +++ b/source/blender/blenlib/intern/bpath.c @@ -199,7 +199,11 @@ void makeFilesAbsolute(Main *bmain, const char *basedir, ReportList *reports) - filesize: filesize for the file */ #define MAX_RECUR 16 -static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth) +static int findFileRecursive(char *filename_new, + const char *dirname, + const char *filename, + int *filesize, + int *recur_depth) { /* file searching stuff */ DIR *dir; @@ -314,7 +318,11 @@ static int rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *abs } } -static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], char path_file[FILE_MAXFILE], BPathVisitor visit_cb, const char *absbase, void *userdata) +static int rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], + char path_file[FILE_MAXFILE], + BPathVisitor visit_cb, + const char *absbase, + void *userdata) { char path_src[FILE_MAX]; char path_dst[FILE_MAX]; @@ -496,7 +504,8 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int fla SEQ_BEGIN(scene->ed, seq) { if (SEQ_HAS_PATH(seq)) { if (ELEM(seq->type, SEQ_MOVIE, SEQ_SOUND)) { - rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, visit_cb, absbase, bpath_user_data); + rewrite_path_fixed_dirfile(seq->strip->dir, seq->strip->stripdata->name, + visit_cb, absbase, bpath_user_data); } else if (seq->type == SEQ_IMAGE) { /* might want an option not to loop over all strips */ @@ -510,7 +519,8 @@ void bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int fla } for(i= 0; i < len; i++, se++) { - rewrite_path_fixed_dirfile(seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data); + rewrite_path_fixed_dirfile(seq->strip->dir, se->name, + visit_cb, absbase, bpath_user_data); } } else { diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 0ea9934d3b6..47deb705def 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -430,6 +430,15 @@ void range_vn_i(int *array_tar, const int size, const int start) while(i--) { *(array_pt--) = j--; } } +void range_vn_fl(float *array_tar, const int size, const float start, const float step) +{ + float *array_pt= array_tar + (size-1); + int i= size; + while(i--) { + *(array_pt--) = start + step * (float)(i); + } +} + void negate_vn(float *array_tar, const int size) { float *array_pt= array_tar + (size-1); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 1edfa2f4ea6..c21bc09ff27 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -330,7 +330,6 @@ static void uiPanelPop(uiBlock *UNUSED(block)) #endif /* triangle 'icon' for panel header */ -/* NOTE - this seems to be only used for hiding nodes now */ void UI_DrawTriIcon(float x, float y, char dir) { if(dir=='h') { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index b89a80bb0d7..c535f2c1ad0 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1071,18 +1071,16 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) /* copy to int, gets projected if possible too */ x1= x1f; y1= y1f; x2= x2f; y2= y2f; - if(butregion) { - if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) { - UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1); - UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2); - } - - x1 += butregion->winrct.xmin; - x2 += butregion->winrct.xmin; - y1 += butregion->winrct.ymin; - y2 += butregion->winrct.ymin; + if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) { + UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1); + UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2); } - + + x1 += butregion->winrct.xmin; + x2 += butregion->winrct.xmin; + y1 += butregion->winrct.ymin; + y2 += butregion->winrct.ymin; + wm_window_get_size(CTX_wm_window(C), &winx, &winy); if(x2 > winx) { @@ -1096,7 +1094,8 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) x2= winx; } } - if(y1 < 0) { /* XXX butregion NULL check?, there is one above */ + + if(y1 < 0) { int newy1; UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->y2 + ofsy, NULL, &newy1); newy1 += butregion->winrct.ymin; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 4020d6923e4..4eed6195dfe 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -894,7 +894,7 @@ static void moveCloserToDistanceFromPlane(Scene *scene, Object *ob, Mesh *me, in int totweight = dvert->totweight; float oldw = 0; float oldPos[3] = {0}; - float vc, hc, dist; + float vc, hc, dist = 0.0f; int i, k; float (*changes)[2] = MEM_mallocN(sizeof(float *)*totweight*2, "vertHorzChange"); float *dists = MEM_mallocN(sizeof(float)*totweight, "distance"); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 98a48ca3bb4..9fdf59b0349 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1688,7 +1688,7 @@ static void calc_flatten_center(Sculpt *sd, Object *ob, PBVHNode **nodes, int to if(ss->cache->original) { BLI_pbvh_vertex_iter_begin(ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { if(sculpt_brush_test_fast(&test, unode->co[vd.i])) { - add_v3_v3(private_fc, vd.co); + add_v3_v3(private_fc, unode->co[vd.i]); private_count++; } } @@ -1758,7 +1758,7 @@ static void calc_area_normal_and_flatten_center(Sculpt *sd, Object *ob, PBVHNode add_norm_if(ss->cache->view_normal, private_an, private_out_flip, fno); // fc - add_v3_v3(private_fc, vd.co); + add_v3_v3(private_fc, unode->co[vd.i]); private_count++; } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 67b4c43343e..08e073494bb 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -562,6 +562,18 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) } +/* common handle function for operator buttons that need to select the node first */ +static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_argv) +{ + bNode *node = (bNode*)node_argv; + const char *opname = (const char *)op_argv; + + /* select & activate only the button's node */ + node_select_single(C, node); + + WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL); +} + static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) { bNodeSocket *sock; @@ -601,39 +613,34 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); - /* show/hide icons, note this sequence is copied in do_header_node() node_state.c */ + /* show/hide icons */ iconofs= rct->xmax - 7.0f; + /* preview */ if(node->typeinfo->flag & NODE_PREVIEW) { - float alpha = (node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))? 1.0f: 0.5f; - + uiBut *but; iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_MATERIAL, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, alpha, ""); + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_MATERIAL, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_preview_toggle"); + /* XXX this does not work when node is activated and the operator called right afterwards, + * since active ID is not updated yet (needs to process the notifier). + * This can only work as visual indicator! + */ +// if (!(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))) +// uiButSetFlag(but, UI_BUT_DISABLED); + uiBlockSetEmboss(node->block, UI_EMBOSS); } + /* group edit */ if(node->type == NODE_GROUP) { - - iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_NODETREE, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); - } - if(node->typeinfo->flag & NODE_OPTIONS) { - iconofs-=iconbutw; - uiDefIconBut(node->block, LABEL, B_REDR, ICON_BUTS, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); - } - { /* always hide/reveal unused sockets */ - // XXX re-enable - /* int shade; - if(node_has_hidden_sockets(node)) - shade= -40; - else - shade= -90; */ - + uiBut *but; iconofs-=iconbutw; - - uiDefIconBut(node->block, LABEL, B_REDR, ICON_PLUS, iconofs, rct->ymax-NODE_DY, - iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefIconBut(node->block, TOGBUT, B_REDR, ICON_NODETREE, + iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_group_edit"); + uiBlockSetEmboss(node->block, UI_EMBOSS); } /* title */ @@ -643,7 +650,19 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); /* open/close entirely? */ - UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); + { + uiBut *but; + int but_size = UI_UNIT_X *0.6f; + /* XXX button uses a custom triangle draw below, so make it invisible without icon */ + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefBut(node->block, TOGBUT, B_REDR, "", + rct->xmin+10.0f-but_size/2, rct->ymax-NODE_DY/2.0f-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); + + /* custom draw function for this button */ + UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); + } /* this isn't doing anything for the label, so commenting out if(node->flag & SELECT) @@ -789,7 +808,19 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); /* open entirely icon */ - UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); + { + uiBut *but; + int but_size = UI_UNIT_X *0.6f; + /* XXX button uses a custom triangle draw below, so make it invisible without icon */ + uiBlockSetEmboss(node->block, UI_EMBOSSN); + but = uiDefBut(node->block, TOGBUT, B_REDR, "", + rct->xmin+10.0f-but_size/2, centy-but_size/2, but_size, but_size, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(but, node_toggle_button_cb, node, (void*)"NODE_OT_hide_toggle"); + uiBlockSetEmboss(node->block, UI_EMBOSS); + + /* custom draw function for this button */ + UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); + } /* disable lines */ if(node->flag & NODE_MUTED) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index e5a216d42b0..87a56274035 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -690,108 +690,6 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) } } -static int compare_nodes(bNode *a, bNode *b) -{ - bNode *parent; - /* These tell if either the node or any of the parent nodes is selected. - * A selected parent means an unselected node is also in foreground! - */ - int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT); - int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE); - - /* if one is an ancestor of the other */ - /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ - for (parent = a->parent; parent; parent=parent->parent) { - /* if b is an ancestor, it is always behind a */ - if (parent==b) - return 1; - /* any selected ancestor moves the node forward */ - if (parent->flag & NODE_ACTIVE) - a_active = 1; - if (parent->flag & NODE_SELECT) - a_select = 1; - } - for (parent = b->parent; parent; parent=parent->parent) { - /* if a is an ancestor, it is always behind b */ - if (parent==a) - return 0; - /* any selected ancestor moves the node forward */ - if (parent->flag & NODE_ACTIVE) - b_active = 1; - if (parent->flag & NODE_SELECT) - b_select = 1; - } - - /* if one of the nodes is in the background and the other not */ - if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) - return 0; - else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) - return 1; - - /* if one has a higher selection state (active > selected > nothing) */ - if (!b_active && a_active) - return 1; - else if (!b_select && (a_active || a_select)) - return 1; - - return 0; -} -/* Sorts nodes by selection: unselected nodes first, then selected, - * then the active node at the very end. Relative order is kept intact! - */ -void node_sort(bNodeTree *ntree) -{ - /* merge sort is the algorithm of choice here */ - bNode *first_a, *first_b, *node_a, *node_b, *tmp; - int totnodes= BLI_countlist(&ntree->nodes); - int k, a, b; - - k = 1; - while (k < totnodes) { - first_a = first_b = ntree->nodes.first; - - do { - /* setup first_b pointer */ - for (b=0; b < k && first_b; ++b) { - first_b = first_b->next; - } - /* all batches merged? */ - if (first_b==NULL) - break; - - /* merge batches */ - node_a = first_a; - node_b = first_b; - a = b = 0; - while (a < k && b < k && node_b) { - if (compare_nodes(node_a, node_b)==0) { - node_a = node_a->next; - ++a; - } - else { - tmp = node_b; - node_b = node_b->next; - ++b; - BLI_remlink(&ntree->nodes, tmp); - BLI_insertlinkbefore(&ntree->nodes, node_a, tmp); - } - } - - /* setup first pointers for next batch */ - first_b = node_b; - for (; b < k; ++b) { - /* all nodes sorted? */ - if (first_b==NULL) - break; - first_b = first_b->next; - } - first_a = first_b; - } while (first_b); - - k = k << 1; - } -} - static int inside_rctf(rctf *bounds, rctf *rect) { return (bounds->xmin <= rect->xmin && bounds->xmax >= rect->xmax @@ -940,7 +838,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(C); if (snode->nodetree==snode->edittree) { - bNode *gnode= nodeGetActive(snode->nodetree); + bNode *gnode = nodeGetActive(snode->edittree); snode_make_group_editable(snode, gnode); } else @@ -955,8 +853,11 @@ static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e { SpaceNode *snode = CTX_wm_space_node(C); bNode *gnode; - - gnode= nodeGetActive(snode->edittree); + + gnode = nodeGetActive(snode->edittree); + if (!gnode) + return OPERATOR_CANCELLED; + /* XXX callback? */ if(gnode && gnode->id && GS(gnode->id->name)==ID_NT && gnode->id->lib) { uiPupMenuOkee(C, op->type->idname, "Make group local?"); @@ -1696,90 +1597,8 @@ void NODE_OT_resize(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING; } -/* ********************** select ******************** */ - - -/* no undo here! */ -void node_deselectall(SpaceNode *snode) -{ - bNode *node; - - for(node= snode->edittree->nodes.first; node; node= node->next) - node->flag &= ~SELECT; -} -/* return 1 if we need redraw otherwise zero. */ -int node_select_same_type(SpaceNode *snode) -{ - bNode *nac, *p; - int redraw; - - /* search for the active node. */ - for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { - if (nac->flag & SELECT) - break; - } - - /* no active node, return. */ - if (!nac) - return(0); - - redraw= 0; - for (p= snode->edittree->nodes.first; p; p= p->next) { - if (p->type != nac->type && p->flag & SELECT) { - /* if it's selected but different type, unselect */ - redraw= 1; - p->flag &= ~SELECT; - } - else if (p->type == nac->type && (!(p->flag & SELECT))) { - /* if it's the same type and is not selected, select! */ - redraw= 1; - p->flag |= SELECT; - } - } - return(redraw); -} - -/* return 1 if we need redraw, otherwise zero. - * dir can be 0 == next or 0 != prev. - */ -int node_select_same_type_np(SpaceNode *snode, int dir) -{ - bNode *nac, *p; - - /* search the active one. */ - for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { - if (nac->flag & SELECT) - break; - } - - /* no active node, return. */ - if (!nac) - return(0); - - if (dir == 0) - p= nac->next; - else - p= nac->prev; - - while (p) { - /* Now search the next with the same type. */ - if (p->type == nac->type) - break; - - if (dir == 0) - p= p->next; - else - p= p->prev; - } - - if (p) { - node_deselectall(snode); - p->flag |= SELECT; - return(1); - } - return(0); -} +/* ********************** hidden sockets ******************** */ int node_has_hidden_sockets(bNode *node) { @@ -1794,6 +1613,31 @@ int node_has_hidden_sockets(bNode *node) return 0; } +/* note: call node_tree_verify_groups(snode->nodetree) after this + */ +void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) +{ + bNodeSocket *sock; + + if(set==0) { + for(sock= node->inputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_HIDDEN; + for(sock= node->outputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_HIDDEN; + } + else { + /* hide unused sockets */ + for(sock= node->inputs.first; sock; sock= sock->next) { + if(sock->link==NULL) + sock->flag |= SOCK_HIDDEN; + } + for(sock= node->outputs.first; sock; sock= sock->next) { + if(nodeCountSocketLinks(snode->edittree, sock)==0) + sock->flag |= SOCK_HIDDEN; + } + } +} + static void node_link_viewer(SpaceNode *snode, bNode *tonode) { bNode *node; @@ -2232,7 +2076,7 @@ bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene, bNodeTemplate { bNode *node= NULL, *gnode; - node_deselectall(snode); + node_deselect_all(snode); node = nodeAddNode(snode->edittree, ntemp); @@ -3130,15 +2974,21 @@ void NODE_OT_group_make(wmOperatorType *ot) static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) { - int tot_eq= 0, tot_neq= 0; bNode *node; + int tot_eq= 0, tot_neq= 0; + /* Toggles the flag on all selected nodes. + * If the flag is set on all nodes it is unset. + * If the flag is not set on all nodes, it is set. + */ for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { - + if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) continue; - + if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0) + continue; + if(node->flag & toggle_flag) tot_eq++; else @@ -3147,10 +2997,12 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) } for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { - + if(toggle_flag== NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW)==0) continue; - + if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0) + continue; + if( (tot_eq && tot_neq) || tot_eq==0) node->flag |= toggle_flag; else @@ -3159,7 +3011,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) } } -static int node_hide_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); @@ -3182,14 +3034,14 @@ void NODE_OT_hide_toggle(wmOperatorType *ot) ot->idname= "NODE_OT_hide_toggle"; /* callbacks */ - ot->exec= node_hide_exec; + ot->exec= node_hide_toggle_exec; ot->poll= ED_operator_node_active; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static int node_preview_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_preview_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); @@ -3214,7 +3066,37 @@ void NODE_OT_preview_toggle(wmOperatorType *ot) ot->idname= "NODE_OT_preview_toggle"; /* callbacks */ - ot->exec= node_preview_exec; + ot->exec= node_preview_toggle_exec; + ot->poll= ED_operator_node_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode= CTX_wm_space_node(C); + + /* sanity checking (poll callback checks this already) */ + if((snode == NULL) || (snode->edittree == NULL)) + return OPERATOR_CANCELLED; + + node_flag_toggle_exec(snode, NODE_OPTIONS); + + snode_notify(C, snode); + + return OPERATOR_FINISHED; +} + +void NODE_OT_options_toggle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Toggle Node Options"; + ot->description= "Toggle option buttons display for selected nodes"; + ot->idname= "NODE_OT_options_toggle"; + + /* callbacks */ + ot->exec= node_options_toggle_exec; ot->poll= ED_operator_node_active; /* flags */ @@ -3225,7 +3107,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode= CTX_wm_space_node(C); bNode *node; - int hidden= 0; + int hidden; /* sanity checking (poll callback checks this already) */ if((snode == NULL) || (snode->edittree == NULL)) @@ -3233,6 +3115,8 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ED_preview_kill_jobs(C); + /* Toggle for all selected nodes */ + hidden = 0; for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { if(node_has_hidden_sockets(node)) { @@ -3241,7 +3125,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op)) } } } - + for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & SELECT) { node_set_hidden_sockets(snode, node, !hidden); @@ -3570,7 +3454,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) } } - node_deselectall(snode); + node_deselect_all(snode); if (snode->nodetree->type==NTREE_COMPOSIT) ntemp.type = CMP_NODE_IMAGE; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 88b81d0855c..9068493360e 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -82,17 +82,23 @@ void node_operatortypes(void); void node_keymap(wmKeyConfig *keyconf); /* node_select.c */ +void node_deselect_all(struct SpaceNode *snode); +int node_select_same_type(struct SpaceNode *snode); +int node_select_same_type_np(struct SpaceNode *snode, int dir); +void node_select_single(struct bContext *C, struct bNode *node); + void NODE_OT_select(struct wmOperatorType *ot); void NODE_OT_select_all(wmOperatorType *ot); void NODE_OT_select_linked_to(wmOperatorType *ot); void NODE_OT_select_linked_from(wmOperatorType *ot); -void NODE_OT_visibility_toggle(struct wmOperatorType *ot); -void NODE_OT_view_all(struct wmOperatorType *ot); void NODE_OT_select_border(struct wmOperatorType *ot); void NODE_OT_select_same_type(struct wmOperatorType *ot); void NODE_OT_select_same_type_next(wmOperatorType *ot); void NODE_OT_select_same_type_prev(wmOperatorType *ot); +/* node_state.c */ +void NODE_OT_view_all(struct wmOperatorType *ot); + /* drawnode.c */ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link); void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 ); @@ -108,10 +114,6 @@ void snode_dag_update(bContext *C, SpaceNode *snode); bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene, struct bNodeTemplate *ntemp, float locx, float locy); void snode_set_context(SpaceNode *snode, Scene *scene); void snode_make_group_editable(SpaceNode *snode, bNode *gnode); -void node_sort(struct bNodeTree *ntree); -void node_deselectall(SpaceNode *snode); -int node_select_same_type(SpaceNode *snode); -int node_select_same_type_np(SpaceNode *snode, int dir); void snode_composite_job(const struct bContext *C, ScrArea *sa); bNode *node_tree_get_editgroup(bNodeTree *ntree); void node_tree_verify_groups(bNodeTree *nodetree); @@ -141,6 +143,7 @@ void NODE_OT_mute_toggle(struct wmOperatorType *ot); void NODE_OT_hide_toggle(struct wmOperatorType *ot); void NODE_OT_hide_socket_toggle(struct wmOperatorType *ot); void NODE_OT_preview_toggle(struct wmOperatorType *ot); +void NODE_OT_options_toggle(struct wmOperatorType *ot); void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 8309181ddda..b5c435b50e8 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -59,10 +59,11 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_select_same_type_prev); WM_operatortype_append(NODE_OT_view_all); - WM_operatortype_append(NODE_OT_visibility_toggle); + WM_operatortype_append(NODE_OT_mute_toggle); WM_operatortype_append(NODE_OT_hide_toggle); WM_operatortype_append(NODE_OT_preview_toggle); + WM_operatortype_append(NODE_OT_options_toggle); WM_operatortype_append(NODE_OT_hide_socket_toggle); WM_operatortype_append(NODE_OT_show_cyclic_dependencies); @@ -148,7 +149,6 @@ void node_keymap(struct wmKeyConfig *keyconf) /* each of these falls through if not handled... */ WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NODE_OT_visibility_toggle", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NODE_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_select_link_viewer", LEFTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index c863efada9f..15efd65450c 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -31,6 +31,8 @@ #include <stdio.h> +#include "BLI_listbase.h" + #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -68,6 +70,206 @@ static bNode *node_under_mouse(bNodeTree *ntree, int mx, int my) return NULL; } +static int compare_nodes(bNode *a, bNode *b) +{ + bNode *parent; + /* These tell if either the node or any of the parent nodes is selected. + * A selected parent means an unselected node is also in foreground! + */ + int a_select=(a->flag & NODE_SELECT), b_select=(b->flag & NODE_SELECT); + int a_active=(a->flag & NODE_ACTIVE), b_active=(b->flag & NODE_ACTIVE); + + /* if one is an ancestor of the other */ + /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ + for (parent = a->parent; parent; parent=parent->parent) { + /* if b is an ancestor, it is always behind a */ + if (parent==b) + return 1; + /* any selected ancestor moves the node forward */ + if (parent->flag & NODE_ACTIVE) + a_active = 1; + if (parent->flag & NODE_SELECT) + a_select = 1; + } + for (parent = b->parent; parent; parent=parent->parent) { + /* if a is an ancestor, it is always behind b */ + if (parent==a) + return 0; + /* any selected ancestor moves the node forward */ + if (parent->flag & NODE_ACTIVE) + b_active = 1; + if (parent->flag & NODE_SELECT) + b_select = 1; + } + + /* if one of the nodes is in the background and the other not */ + if ((a->flag & NODE_BACKGROUND) && !(b->flag & NODE_BACKGROUND)) + return 0; + else if (!(a->flag & NODE_BACKGROUND) && (b->flag & NODE_BACKGROUND)) + return 1; + + /* if one has a higher selection state (active > selected > nothing) */ + if (!b_active && a_active) + return 1; + else if (!b_select && (a_active || a_select)) + return 1; + + return 0; +} + +/* Sorts nodes by selection: unselected nodes first, then selected, + * then the active node at the very end. Relative order is kept intact! + */ +static void node_sort(bNodeTree *ntree) +{ + /* merge sort is the algorithm of choice here */ + bNode *first_a, *first_b, *node_a, *node_b, *tmp; + int totnodes= BLI_countlist(&ntree->nodes); + int k, a, b; + + k = 1; + while (k < totnodes) { + first_a = first_b = ntree->nodes.first; + + do { + /* setup first_b pointer */ + for (b=0; b < k && first_b; ++b) { + first_b = first_b->next; + } + /* all batches merged? */ + if (first_b==NULL) + break; + + /* merge batches */ + node_a = first_a; + node_b = first_b; + a = b = 0; + while (a < k && b < k && node_b) { + if (compare_nodes(node_a, node_b)==0) { + node_a = node_a->next; + ++a; + } + else { + tmp = node_b; + node_b = node_b->next; + ++b; + BLI_remlink(&ntree->nodes, tmp); + BLI_insertlinkbefore(&ntree->nodes, node_a, tmp); + } + } + + /* setup first pointers for next batch */ + first_b = node_b; + for (; b < k; ++b) { + /* all nodes sorted? */ + if (first_b==NULL) + break; + first_b = first_b->next; + } + first_a = first_b; + } while (first_b); + + k = k << 1; + } +} + +/* no undo here! */ +void node_deselect_all(SpaceNode *snode) +{ + bNode *node; + + for(node= snode->edittree->nodes.first; node; node= node->next) + node->flag &= ~SELECT; +} + +/* return 1 if we need redraw otherwise zero. */ +int node_select_same_type(SpaceNode *snode) +{ + bNode *nac, *p; + int redraw; + + /* search for the active node. */ + for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { + if (nac->flag & SELECT) + break; + } + + /* no active node, return. */ + if (!nac) + return(0); + + redraw= 0; + for (p= snode->edittree->nodes.first; p; p= p->next) { + if (p->type != nac->type && p->flag & SELECT) { + /* if it's selected but different type, unselect */ + redraw= 1; + p->flag &= ~SELECT; + } + else if (p->type == nac->type && (!(p->flag & SELECT))) { + /* if it's the same type and is not selected, select! */ + redraw= 1; + p->flag |= SELECT; + } + } + return(redraw); +} + +/* return 1 if we need redraw, otherwise zero. + * dir can be 0 == next or 0 != prev. + */ +int node_select_same_type_np(SpaceNode *snode, int dir) +{ + bNode *nac, *p; + + /* search the active one. */ + for (nac= snode->edittree->nodes.first; nac; nac= nac->next) { + if (nac->flag & SELECT) + break; + } + + /* no active node, return. */ + if (!nac) + return(0); + + if (dir == 0) + p= nac->next; + else + p= nac->prev; + + while (p) { + /* Now search the next with the same type. */ + if (p->type == nac->type) + break; + + if (dir == 0) + p= p->next; + else + p= p->prev; + } + + if (p) { + node_deselect_all(snode); + p->flag |= SELECT; + return(1); + } + return(0); +} + +void node_select_single(bContext *C, bNode *node) +{ + Main *bmain= CTX_data_main(C); + SpaceNode *snode= CTX_wm_space_node(C); + + node_deselect_all(snode); + node->flag |= SELECT; + + ED_node_set_active(bmain, snode->edittree, node); + + node_sort(snode->edittree); + + WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL); +} + /* ****** Click Select ****** */ static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend) @@ -86,7 +288,7 @@ static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, cons if (node) { if (extend == 0) { - node_deselectall(snode); + node_deselect_all(snode); node->flag |= SELECT; } else diff --git a/source/blender/editors/space_node/node_state.c b/source/blender/editors/space_node/node_state.c index bfebd087c3f..58623e17b10 100644 --- a/source/blender/editors/space_node/node_state.c +++ b/source/blender/editors/space_node/node_state.c @@ -52,160 +52,6 @@ #include "node_intern.h" -/* **************** Node Header Buttons ************** */ - -/* note: call node_tree_verify_groups(snode->nodetree) after this - */ -void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) -{ - bNodeSocket *sock; - - if(set==0) { - for(sock= node->inputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_HIDDEN; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_HIDDEN; - } - else { - /* hide unused sockets */ - for(sock= node->inputs.first; sock; sock= sock->next) { - if(sock->link==NULL) - sock->flag |= SOCK_HIDDEN; - } - for(sock= node->outputs.first; sock; sock= sock->next) { - if(nodeCountSocketLinks(snode->edittree, sock)==0) - sock->flag |= SOCK_HIDDEN; - } - } -} - -static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node) -{ - node_set_hidden_sockets(snode, node, !node_has_hidden_sockets(node)); - ntreeUpdateTree(snode->edittree); -} - -static int do_header_node(SpaceNode *snode, bNode *node, float mx, float my) -{ - rctf totr= node->totr; - - totr.ymin= totr.ymax-20.0f; - - totr.xmax= totr.xmin+15.0f; - if(BLI_in_rctf(&totr, mx, my)) { - node->flag |= NODE_HIDDEN; - return 1; - } - - totr.xmax= node->totr.xmax; - totr.xmin= totr.xmax-18.0f; - if(node->typeinfo->flag & NODE_PREVIEW) { - if(BLI_in_rctf(&totr, mx, my)) { - node->flag ^= NODE_PREVIEW; - return 1; - } - totr.xmin-=15.0f; - } - if(node->type == NODE_GROUP) { - if(BLI_in_rctf(&totr, mx, my)) { - snode_make_group_editable(snode, node); - return 1; - } - totr.xmin-=15.0f; - } - if(node->typeinfo->flag & NODE_OPTIONS) { - if(BLI_in_rctf(&totr, mx, my)) { - node->flag ^= NODE_OPTIONS; - return 1; - } - totr.xmin-=15.0f; - } - /* hide unused sockets */ - if(BLI_in_rctf(&totr, mx, my)) { - node_hide_unhide_sockets(snode, node); - } - - return 0; -} - -static int do_header_hidden_node(bNode *node, float mx, float my) -{ - rctf totr= node->totr; - - totr.xmax= totr.xmin+15.0f; - if(BLI_in_rctf(&totr, mx, my)) { - node->flag &= ~NODE_HIDDEN; - return 1; - } - return 0; -} - -static int node_toggle_visibility(SpaceNode *snode, ARegion *ar, const int mval[2]) -{ - bNode *node; - float mx, my; - - mx= (float)mval[0]; - my= (float)mval[1]; - - UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); - - for(node=snode->edittree->nodes.last; node; node=node->prev) { - if(node->flag & NODE_HIDDEN) { - if(do_header_hidden_node(node, mx, my)) { - ED_region_tag_redraw(ar); - return 1; - } - } - else { - if(do_header_node(snode, node, mx, my)) { - ED_region_tag_redraw(ar); - return 1; - } - } - } - return 0; -} - -static int node_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - SpaceNode *snode= CTX_wm_space_node(C); - ARegion *ar= CTX_wm_region(C); - int mval[2]; - - mval[0] = RNA_int_get(op->ptr, "mouse_x"); - mval[1] = RNA_int_get(op->ptr, "mouse_y"); - if(node_toggle_visibility(snode, ar, mval)) - return OPERATOR_FINISHED; - else - return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; -} - -static int node_toggle_visibility_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - RNA_int_set(op->ptr, "mouse_x", event->mval[0]); - RNA_int_set(op->ptr, "mouse_y", event->mval[1]); - - return node_toggle_visibility_exec(C,op); -} - -void NODE_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Toggle Visibility"; - ot->idname= "NODE_OT_visibility_toggle"; - ot->description= "Handle clicks on node header buttons"; - - /* api callbacks */ - ot->invoke= node_toggle_visibility_invoke; - ot->poll= ED_operator_node_active; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_int(ot->srna, "mouse_x", 0, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "mouse_y", 0, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX); -} /* **************** View All Operator ************** */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index a151275e109..18e61f7300e 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -724,8 +724,7 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - cent[0] += luv->uv[0]; - cent[1] += luv->uv[1]; + add_v2_v2(cent, luv->uv); } cent[0] /= efa->len; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 4c0a3d6c5e4..eaa661a9dcf 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -112,6 +112,8 @@ void GPU_extensions_init(void) if (!GLEW_ARB_vertex_shader) GG.glslsupport = 0; if (!GLEW_ARB_fragment_shader) GG.glslsupport = 0; + GPU_code_generate_glsl_lib(); + glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_BLUE_BITS, &b); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index c588dc9c8ac..c15758eed1f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -64,9 +64,13 @@ EnumPropertyItem nodetree_type_items[] = { EnumPropertyItem node_socket_type_items[] = { - {SOCK_FLOAT, "VALUE", 0, "Value", ""}, - {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, - {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, + {SOCK_FLOAT, "VALUE", 0, "Value", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, + {SOCK_SHADER, "SHADER", 0, "Shader", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_MESH, "MESH", 0, "Mesh", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem node_math_items[] = { diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 31f7f49aa80..d7a2ddd62d0 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -810,11 +810,11 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) if(value) { ob->matbits[index]= 1; - ob->colbits |= (1<<index); + /* ob->colbits |= (1<<index); */ /* DEPRECATED */ } else { ob->matbits[index]= 0; - ob->colbits &= ~(1<<index); + /* ob->colbits &= ~(1<<index); */ /* DEPRECATED */ } } diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 95cb8b38eaa..d8a78ac1f97 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -191,13 +191,12 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ if( tmpcu->mat ) { for( i = tmpcu->totcol; i-- > 0; ) { /* are we an object material or data based? */ - if (ob->colbits & 1<<i) - tmpmesh->mat[i] = ob->mat[i]; - else - tmpmesh->mat[i] = tmpcu->mat[i]; - if (tmpmesh->mat[i]) + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpcu->mat[i]; + + if (tmpmesh->mat[i]) { tmpmesh->mat[i]->id.us++; + } } } break; @@ -230,12 +229,11 @@ Mesh *rna_Object_to_mesh(Object *ob, ReportList *reports, Scene *sce, int apply_ if( origmesh->mat ) { for( i = origmesh->totcol; i-- > 0; ) { /* are we an object material or data based? */ - if (ob->colbits & 1<<i) - tmpmesh->mat[i] = ob->mat[i]; - else - tmpmesh->mat[i] = origmesh->mat[i]; - if (tmpmesh->mat[i]) + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : origmesh->mat[i]; + + if (tmpmesh->mat[i]) { tmpmesh->mat[i]->id.us++; + } } } } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index f0a008b4939..a7f45d867dd 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2000,23 +2000,6 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_enum_items(prop, proxy_render_size_items); RNA_def_property_ui_text(prop, "Proxy render size", "Draw preview using full resolution or different proxy resolutions"); RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL); - - - /* not sure we need rna access to these but adding anyway */ - prop= RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "xof"); - RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally from the view center"); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL); - - prop= RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "yof"); - RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the view center"); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL); - - prop= RNA_def_property(srna, "zoom", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "zoom"); - RNA_def_property_ui_text(prop, "Zoom", "Display zoom level"); - RNA_def_property_update(prop, NC_SPACE|ND_SPACE_SEQUENCER, NULL); } static void rna_def_space_text(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 86e16df0be5..0da5135ac26 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -79,8 +79,8 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3]) /* we don't want to overwrite any referenced layers */ /* - Dosnt work here! - mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT); + Doesn't work here! + mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts); cddm->mvert = mv; */ diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index bd82001dd1b..8f2d248b956 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -259,11 +259,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); } + numFaces = dm->getNumTessFaces(dm); + /* make sure we are not modifying the original UV map */ tface = CustomData_duplicate_referenced_layer_named(&dm->faceData, - CD_MTFACE, uvname); + CD_MTFACE, uvname, numFaces); - numVerts = dm->getNumVerts(dm); coords = MEM_callocN(sizeof(*coords) * numVerts, @@ -295,15 +296,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, } else { /* apply transformed coords as UVs */ - tface->uv[0][0] = coords[mf->v1][0]; - tface->uv[0][1] = coords[mf->v1][1]; - tface->uv[1][0] = coords[mf->v2][0]; - tface->uv[1][1] = coords[mf->v2][1]; - tface->uv[2][0] = coords[mf->v3][0]; - tface->uv[2][1] = coords[mf->v3][1]; - if(mf->v4) { - tface->uv[3][0] = coords[mf->v4][0]; - tface->uv[3][1] = coords[mf->v4][1]; + copy_v2_v2(tface->uv[0], coords[mf->v1]); + copy_v2_v2(tface->uv[1], coords[mf->v2]); + copy_v2_v2(tface->uv[2], coords[mf->v3]); + if (mf->v4) { + copy_v2_v2(tface->uv[3], coords[mf->v4]); } } } else { @@ -358,15 +355,11 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, mul_project_m4_v3(best_projector->projmat, co4); /* apply transformed coords as UVs */ - tface->uv[0][0] = co1[0]; - tface->uv[0][1] = co1[1]; - tface->uv[1][0] = co2[0]; - tface->uv[1][1] = co2[1]; - tface->uv[2][0] = co3[0]; - tface->uv[2][1] = co3[1]; - if(mf->v4) { - tface->uv[3][0] = co4[0]; - tface->uv[3][1] = co4[1]; + copy_v2_v2(tface->uv[0], co1); + copy_v2_v2(tface->uv[1], co2); + copy_v2_v2(tface->uv[2], co3); + if (mf->v4) { + copy_v2_v2(tface->uv[3], co4); } } } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 8b44f262e41..db561eb59a6 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -449,9 +449,17 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der MEM_freeN(tdw); /* Get our vertex coordinates. */ - v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos"); - for (i = 0; i < numIdx; i++) - ret->getVertCo(ret, indices[i], v_cos[i]); + { + /* XXX In some situations, this code can be up to about 50 times more performant + * than simply using getVertCo for each affected vertex... + */ + float (*tv_cos)[3] = MEM_mallocN(sizeof(float[3]) * numVerts, "WeightVGProximity Modifier, tv_cos"); + v_cos = MEM_mallocN(sizeof(float[3]) * numIdx, "WeightVGProximity Modifier, v_cos"); + ret->getVertCos(ret, tv_cos); + for (i = 0; i < numIdx; i++) + copy_v3_v3(v_cos[i], tv_cos[indices[i]]); + MEM_freeN(tv_cos); + } /* Compute wanted distances. */ if (wmd->proximity_mode == MOD_WVG_PROXIMITY_OBJECT) { diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 03d66e918d5..c2fd6036414 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -453,7 +453,7 @@ static int Buffer_ass_item(Buffer *self, int i, PyObject *v) } } - switch(self->type) { + switch (self->type) { case GL_BYTE: return PyArg_Parse(v, "b:Expected ints", &self->buf.asbyte[i]) ? 0:-1; case GL_SHORT: @@ -595,7 +595,7 @@ static PyObject *Buffer_repr(Buffer *self) PyObject *repr; const char *typestr= "UNKNOWN"; - switch(self->type) { + switch (self->type) { case GL_BYTE: typestr= "GL_BYTE"; break; case GL_SHORT: typestr= "GL_SHORT"; break; case GL_INT: typestr= "GL_BYTE"; break; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index c31dadff3e1..c058ee1d4f0 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -405,7 +405,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty val.array.len = PySequence_Size(ob); - switch(val.array.type) { + switch (val.array.type) { case IDP_DOUBLE: prop = IDP_New(IDP_ARRAY, &val, name); for (i=0; i<val.array.len; i++) { @@ -565,7 +565,7 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) return NULL; } - switch(prop->subtype) { + switch (prop->subtype) { case IDP_FLOAT: { float *array= (float*)IDP_Array(prop); @@ -976,7 +976,7 @@ static PyObject *BPy_IDArray_repr(BPy_IDArray *self) static PyObject *BPy_IDArray_GetType(BPy_IDArray *self) { - switch(self->prop->subtype) { + switch (self->prop->subtype) { case IDP_FLOAT: return PyUnicode_FromString("f"); case IDP_DOUBLE: diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 8d68a407e62..43b8dc21300 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -191,7 +191,7 @@ void PyC_FileAndNum(const char **filename, int *lineno) void PyC_FileAndNum_Safe(const char **filename, int *lineno) { - if(!PYC_INTERPRETER_ACTIVE) { + if (!PYC_INTERPRETER_ACTIVE) { return; } diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index dd512791e85..dc9ef9ee8e8 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -82,7 +82,7 @@ static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyO { PyObject *value; - if(!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) + if (!PyArg_ParseTuple(args, "O:bpy.app.handlers.persistent", &value)) return NULL; if (PyFunction_Check(value)) { @@ -252,12 +252,12 @@ void BPY_app_handlers_reset(const short do_all) PyObject *item; PyObject **dict_ptr; - for(i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) { + for (i= PyList_GET_SIZE(ls) - 1; i >= 0; i--) { - if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) && - (dict_ptr= _PyObject_GetDictPtr(item)) && - (*dict_ptr) && - (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) + if ( (PyFunction_Check((item= PyList_GET_ITEM(ls, i)))) && + (dict_ptr= _PyObject_GetDictPtr(item)) && + (*dict_ptr) && + (PyDict_GetItem(*dict_ptr, perm_id_str) != NULL)) { /* keep */ } diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index c0d796669d6..d1408015089 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -971,14 +971,14 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i item= PySequence_Fast_GET_ITEM(seq_fast, i); - if ( (PyTuple_CheckExact(item)) && - (item_size= PyTuple_GET_SIZE(item)) && - (item_size == 3 || item_size == 4) && - (tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && - (tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && - (tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && - (item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) /* TODO, number isnt ensured to be unique from the script author */ - ) { + if ( (PyTuple_CheckExact(item)) && + (item_size= PyTuple_GET_SIZE(item)) && + (item_size == 3 || item_size == 4) && + (tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && + (tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && + (tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && + (item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1)) /* TODO, number isnt ensured to be unique from the script author */ + { if (is_enum_flag) { if (item_size < 4) { tmp.value= 1<<i; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index f099994fc57..69a5fb39b67 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -624,7 +624,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) if (!is_thick) ret= pyrna_prop_CreatePyObject(ptr, prop); /* owned by the mathutils PyObject */ - switch(subtype) { + switch (subtype) { case PROP_ALL_VECTOR_SUBTYPES: if (len>=2 && len <= 4) { if (is_thick) { @@ -3441,7 +3441,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) int done= CTX_data_get(C, name, &newptr, &newlb, &newtype); if (done==1) { /* found */ - switch(newtype) { + switch (newtype) { case CTX_DATA_TYPE_POINTER: if (newptr.data == NULL) { ret= Py_None; @@ -4201,7 +4201,7 @@ static int foreach_compat_buffer(RawPropertyType raw_type, int attr_signed, cons { char f= format ? *format:'B'; /* B is assumed when not set */ - switch(raw_type) { + switch (raw_type) { case PROP_RAW_CHAR: if (attr_signed) return (f=='b') ? 1:0; else return (f=='B') ? 1:0; @@ -4265,7 +4265,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) for ( ; i<tot; i++) { item= PySequence_GetItem(seq, i); - switch(raw_type) { + switch (raw_type) { case PROP_RAW_CHAR: ((char *)array)[i]= (char)PyLong_AsLong(item); break; @@ -4320,7 +4320,7 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) for ( ; i<tot; i++) { - switch(raw_type) { + switch (raw_type) { case PROP_RAW_CHAR: item= PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]); break; @@ -4616,7 +4616,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int*)data)[a])); break; case PROP_FLOAT: - switch(RNA_property_subtype(prop)) { + switch (RNA_property_subtype(prop)) { #ifdef USE_MATHUTILS case PROP_ALL_VECTOR_SUBTYPES: ret= Vector_CreatePyObject(data, len, Py_NEW, NULL); @@ -6969,10 +6969,10 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param if (err != 0) { ReportList *reports; /* alert the user, else they wont know unless they see the console. */ - if ( (!is_static) && - (ptr->data) && - (RNA_struct_is_a(ptr->type, &RNA_Operator)) && - (is_valid_wm == (CTX_wm_manager(C) != NULL))) + if ( (!is_static) && + (ptr->data) && + (RNA_struct_is_a(ptr->type, &RNA_Operator)) && + (is_valid_wm == (CTX_wm_manager(C) != NULL))) { wmOperator *op= ptr->data; reports= op->reports; diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 8f88814b3e4..3006e2a6b90 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -148,8 +148,8 @@ static int pyrna_struct_anim_args_parse( /* internal use for insert and delete */ static int pyrna_struct_keyframe_parse( - PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, - const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ + PointerRNA *ptr, PyObject *args, PyObject *kw, const char *parse_str, const char *error_prefix, + const char **path_full, int *index, float *cfra, const char **group_name) /* return values */ { static const char *kwlist[]= {"data_path", "index", "frame", "group", NULL}; const char *path; diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index 85f950947a7..134cbfda71f 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -60,7 +60,7 @@ static void cb_region_draw(const bContext *C, ARegion *UNUSED(ar), void *customd cb_args= PyTuple_GET_ITEM((PyObject *)customdata, 1); result= PyObject_CallObject(cb_func, cb_args); - if(result) { + if (result) { Py_DECREF(result); } else { @@ -82,21 +82,22 @@ PyObject *pyrna_callback_add(BPy_StructRNA *self, PyObject *args) if (!PyArg_ParseTuple(args, "OO!|s:bpy_struct.callback_add", &cb_func, &PyTuple_Type, &cb_args, &cb_event_str)) return NULL; - if(!PyCallable_Check(cb_func)) { + if (!PyCallable_Check(cb_func)) { PyErr_SetString(PyExc_TypeError, "callback_add(): first argument isn't callable"); return NULL; } - if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { - if(cb_event_str) { + if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + if (cb_event_str) { static EnumPropertyItem region_draw_mode_items[]= { {REGION_DRAW_POST_PIXEL, "POST_PIXEL", 0, "Post Pixel", ""}, {REGION_DRAW_POST_VIEW, "POST_VIEW", 0, "Post View", ""}, {REGION_DRAW_PRE_VIEW, "PRE_VIEW", 0, "Pre View", ""}, {0, NULL, 0, NULL, NULL}}; - if(pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) + if (pyrna_enum_value_from_id(region_draw_mode_items, cb_event_str, &cb_event, "bpy_struct.callback_add()") < 0) { return NULL; + } } else { cb_event= REGION_DRAW_POST_PIXEL; @@ -124,12 +125,12 @@ PyObject *pyrna_callback_remove(BPy_StructRNA *self, PyObject *args) handle= PyCapsule_GetPointer(py_handle, RNA_CAPSULE_ID); - if(handle==NULL) { + if (handle==NULL) { PyErr_SetString(PyExc_ValueError, "callback_remove(handle): NULL handle given, invalid or already removed"); return NULL; } - if(RNA_struct_is_a(self->ptr.type, &RNA_Region)) { + if (RNA_struct_is_a(self->ptr.type, &RNA_Region)) { customdata= ED_region_draw_cb_customdata(handle); Py_DECREF((PyObject *)customdata); diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 0da63297077..a155a7ec3d9 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -184,7 +184,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed"); return NULL; } - } else { + } + else { PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type"); return NULL; } @@ -204,7 +205,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed"); return NULL; } - } else { + } + else { PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type"); return NULL; } @@ -260,7 +262,8 @@ static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObj if (attribute->name) { if (attribute->name[0] != 0) { PY_DICT_ADD_STRING(dict,attribute,name); - } else { + } + else { val = PyLong_FromLong(0); PyDict_SetItemString(dict, "name", val); Py_DECREF(val); diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 121c5e26e73..5587028d812 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -40,36 +40,13 @@ PyDoc_STRVAR(M_Mathutils_doc, "This module provides access to matrices, eulers, quaternions and vectors." ); static int mathutils_array_parse_fast(float *array, - int array_min, int array_max, - PyObject *value, const char *error_prefix) + int size, + PyObject *value_fast, + const char *error_prefix) { - PyObject *value_fast= NULL; PyObject *item; - int i, size; - - /* non list/tuple cases */ - if (!(value_fast=PySequence_Fast(value, error_prefix))) { - /* PySequence_Fast sets the error */ - return -1; - } - - size= PySequence_Fast_GET_SIZE(value_fast); - - if (size > array_max || size < array_min) { - if (array_max == array_min) { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected %d", - error_prefix, size, array_max); - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected [%d - %d]", - error_prefix, size, array_min, array_max); - } - Py_DECREF(value_fast); - return -1; - } + int i; i= size; do { @@ -93,13 +70,14 @@ static int mathutils_array_parse_fast(float *array, /* helper functionm returns length of the 'value', -1 on error */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) { -#if 1 /* approx 6x speedup for mathutils types */ int size; - if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || - (size= EulerObject_Check(value) ? 3 : 0) || - (size= QuaternionObject_Check(value) ? 4 : 0) || - (size= ColorObject_Check(value) ? 3 : 0)) +#if 1 /* approx 6x speedup for mathutils types */ + + if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || + (size= EulerObject_Check(value) ? 3 : 0) || + (size= QuaternionObject_Check(value) ? 4 : 0) || + (size= ColorObject_Check(value) ? 3 : 0)) { if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { return -1; @@ -125,7 +103,85 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * else #endif { - return mathutils_array_parse_fast(array, array_min, array_max, value, error_prefix); + PyObject *value_fast= NULL; + + /* non list/tuple cases */ + if (!(value_fast=PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size= PySequence_Fast_GET_SIZE(value_fast); + + if (size > array_max || size < array_min) { + if (array_max == array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected %d", + error_prefix, size, array_max); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected [%d - %d]", + error_prefix, size, array_min, array_max); + } + Py_DECREF(value_fast); + return -1; + } + + return mathutils_array_parse_fast(array, size, value_fast, error_prefix); + } +} + +int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix) +{ + int size; + +#if 1 /* approx 6x speedup for mathutils types */ + + if ( (size= VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || + (size= EulerObject_Check(value) ? 3 : 0) || + (size= QuaternionObject_Check(value) ? 4 : 0) || + (size= ColorObject_Check(value) ? 3 : 0)) + { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + + if (size < array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected > %d", + error_prefix, size, array_min); + return -1; + } + + *array= PyMem_Malloc(size * sizeof(float)); + memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float)); + return size; + } + else +#endif + { + PyObject *value_fast= NULL; + //*array= NULL; + + /* non list/tuple cases */ + if (!(value_fast=PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size= PySequence_Fast_GET_SIZE(value_fast); + + if (size < array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected > %d", + error_prefix, size, array_min); + return -1; + } + + *array= PyMem_Malloc(size * sizeof(float)); + + return mathutils_array_parse_fast(*array, size, value_fast, error_prefix); } } diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index a8170b8145c..cd3548b9b82 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -115,6 +115,7 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); /* utility func */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); +int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix); int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 8409344a9fe..e46dda7560f 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -48,7 +48,7 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - switch(PyTuple_GET_SIZE(args)) { + switch (PyTuple_GET_SIZE(args)) { case 0: break; case 1: diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 7e769da14cb..f44c0b82a2d 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -59,7 +59,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) return NULL; - switch(PyTuple_GET_SIZE(args)) { + switch (PyTuple_GET_SIZE(args)) { case 0: break; case 2: @@ -84,7 +84,7 @@ static const char *euler_order_str(EulerObject *self) short euler_order_from_string(const char *str, const char *error_prefix) { if ((str[0] && str[1] && str[2] && str[3]=='\0')) { - switch(*((PY_INT32_T *)str)) { + switch (*((PY_INT32_T *)str)) { case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ; case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY; case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index ea636ef52fb..44799bb7943 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -52,13 +52,14 @@ static int mathutils_matrix_vector_check(BaseMathObject *bmo) static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype) { MatrixObject *self= (MatrixObject *)bmo->cb_user; - int i; + int index; if (BaseMath_ReadCallback(self) == -1) return -1; - for (i=0; i < self->col_size; i++) - bmo->data[i]= self->matrix[subtype][i]; + for (index=0; index < self->col_size; index++) { + bmo->data[index] = MATRIX_ITEM(self, subtype, index); + } return 0; } @@ -66,13 +67,14 @@ static int mathutils_matrix_vector_get(BaseMathObject *bmo, int subtype) static int mathutils_matrix_vector_set(BaseMathObject *bmo, int subtype) { MatrixObject *self= (MatrixObject *)bmo->cb_user; - int i; + int index; if (BaseMath_ReadCallback(self) == -1) return -1; - for (i=0; i < self->col_size; i++) - self->matrix[subtype][i]= bmo->data[i]; + for (index=0; index < self->col_size; index++) { + MATRIX_ITEM(self, subtype, index) = bmo->data[index]; + } (void)BaseMath_WriteCallback(self); return 0; @@ -85,7 +87,7 @@ static int mathutils_matrix_vector_get_index(BaseMathObject *bmo, int subtype, i if (BaseMath_ReadCallback(self) == -1) return -1; - bmo->data[index]= self->matrix[subtype][index]; + bmo->data[index]= MATRIX_ITEM(self, subtype, index); return 0; } @@ -96,7 +98,7 @@ static int mathutils_matrix_vector_set_index(BaseMathObject *bmo, int subtype, i if (BaseMath_ReadCallback(self) == -1) return -1; - self->matrix[subtype][index]= bmo->data[index]; + MATRIX_ITEM(self, subtype, index) = bmo->data[index]; (void)BaseMath_WriteCallback(self); return 0; @@ -123,7 +125,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - switch(PyTuple_GET_SIZE(args)) { + switch (PyTuple_GET_SIZE(args)) { case 0: return Matrix_CreatePyObject(NULL, 4, 4, Py_NEW, type); case 1: @@ -620,24 +622,22 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) void matrix_as_3x3(float mat[3][3], MatrixObject *self) { - copy_v3_v3(mat[0], self->matrix[0]); - copy_v3_v3(mat[1], self->matrix[1]); - copy_v3_v3(mat[2], self->matrix[2]); + copy_v3_v3(mat[0], MATRIX_ROW_PTR(self, 0)); + copy_v3_v3(mat[1], MATRIX_ROW_PTR(self, 1)); + copy_v3_v3(mat[2], MATRIX_ROW_PTR(self, 2)); } /* assumes rowsize == colsize is checked and the read callback has run */ static float matrix_determinant_internal(MatrixObject *self) { if (self->row_size == 2) { - return determinant_m2(self->matrix[0][0], self->matrix[0][1], - self->matrix[1][0], self->matrix[1][1]); + return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), + MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1)); } else if (self->row_size == 3) { - return determinant_m3(self->matrix[0][0], self->matrix[0][1], - self->matrix[0][2], self->matrix[1][0], - self->matrix[1][1], self->matrix[1][2], - self->matrix[2][0], self->matrix[2][1], - self->matrix[2][2]); + return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2), + MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2), + MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2)); } else { return determinant_m4((float (*)[4])self->contigPtr); @@ -781,10 +781,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) "problem allocating pointer space"); return NULL; } - /*set row pointers*/ - for (x = 0; x < 4; x++) { - self->matrix[x] = self->contigPtr + (x * 4); - } + /*move data to new spot in array + clean*/ for (blank_rows = (4 - self->row_size); blank_rows > 0; blank_rows--) { for (x = 0; x < 4; x++) { @@ -890,7 +887,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self) return NULL; } - return Vector_CreatePyObject(self->matrix[3], 3, Py_NEW, NULL); + return Vector_CreatePyObject(MATRIX_ROW_PTR(self, 3), 3, Py_NEW, NULL); } PyDoc_STRVAR(Matrix_to_scale_doc, @@ -964,10 +961,10 @@ static PyObject *Matrix_invert(MatrixObject *self) if (det != 0) { /*calculate the classical adjoint*/ if (self->row_size == 2) { - mat[0] = self->matrix[1][1]; - mat[1] = -self->matrix[0][1]; - mat[2] = -self->matrix[1][0]; - mat[3] = self->matrix[0][0]; + mat[0] = MATRIX_ITEM(self, 1, 1); + mat[1] = -MATRIX_ITEM(self, 0, 1); + mat[2] = -MATRIX_ITEM(self, 1, 0); + mat[3] = MATRIX_ITEM(self, 0, 0); } else if (self->row_size == 3) { adjoint_m3_m3((float (*)[3]) mat,(float (*)[3])self->contigPtr); @@ -982,7 +979,7 @@ static PyObject *Matrix_invert(MatrixObject *self) /*set values*/ for (x = 0; x < self->row_size; x++) { for (y = 0; y < self->col_size; y++) { - self->matrix[x][y] = mat[z]; + MATRIX_ITEM(self, x, y) = mat[z]; z++; } } @@ -1173,8 +1170,6 @@ PyDoc_STRVAR(Matrix_transpose_doc, ); static PyObject *Matrix_transpose(MatrixObject *self) { - float t = 0.0f; - if (BaseMath_ReadCallback(self) == -1) return NULL; @@ -1186,9 +1181,9 @@ static PyObject *Matrix_transpose(MatrixObject *self) } if (self->row_size == 2) { - t = self->matrix[1][0]; - self->matrix[1][0] = self->matrix[0][1]; - self->matrix[0][1] = t; + const float t = MATRIX_ITEM(self, 1, 0); + MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1); + MATRIX_ITEM(self, 0, 1) = t; } else if (self->row_size == 3) { transpose_m3((float (*)[3])self->contigPtr); @@ -1256,10 +1251,10 @@ static PyObject *Matrix_identity(MatrixObject *self) } if (self->row_size == 2) { - self->matrix[0][0] = 1.0f; - self->matrix[0][1] = 0.0f; - self->matrix[1][0] = 0.0f; - self->matrix[1][1] = 1.0f; + MATRIX_ITEM(self, 0, 0) = 1.0f; + MATRIX_ITEM(self, 0, 1) = 0.0f; + MATRIX_ITEM(self, 1, 0) = 0.0f; + MATRIX_ITEM(self, 1, 1) = 1.0f; } else if (self->row_size == 3) { unit_m3((float (*)[3])self->contigPtr); @@ -1304,10 +1299,10 @@ static PyObject *Matrix_repr(MatrixObject *self) for (x = 0; x < self->row_size; x++) { rows[x]= PyTuple_New(self->col_size); for (y = 0; y < self->col_size; y++) { - PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(self->matrix[x][y])); + PyTuple_SET_ITEM(rows[x], y, PyFloat_FromDouble(MATRIX_ITEM(self, x, y))); } } - switch(self->row_size) { + switch (self->row_size) { case 2: return PyUnicode_FromFormat("Matrix((%R,\n" " %R))", rows[0], rows[1]); @@ -1406,7 +1401,7 @@ static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value) return -1; } - memcpy(self->matrix[i], vec, self->col_size *sizeof(float)); + memcpy(MATRIX_ROW_PTR(self, i), vec, self->col_size * sizeof(float)); (void)BaseMath_WriteCallback(self); return 0; @@ -1591,7 +1586,7 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) for (x = 0; x < mat2->row_size; x++) { for (y = 0; y < mat1->col_size; y++) { for (z = 0; z < mat1->row_size; z++) { - dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); + dot += MATRIX_ITEM(mat1, z, y) * MATRIX_ITEM(mat2, x, z); } mat[((x * mat1->col_size) + y)] = (float)dot; dot = 0.0f; @@ -1944,31 +1939,18 @@ PyTypeObject matrix_Type = { NULL /*tp_del*/ }; -/*------------------------Matrix_CreatePyObject (internal)------------- -creates a new matrix object -self->matrix self->contiguous_ptr (reference to data.xxx) - [0]------------->[0] - [1] - [2] - [1]------------->[3] - [4] - [5] - -self->matrix[1][1] = self->contigPtr[4] */ - -/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER - (i.e. it was allocated elsewhere by MEM_mallocN()) - pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON - (i.e. it must be created here with PyMEM_malloc())*/ +/* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER + * (i.e. it was allocated elsewhere by MEM_mallocN()) + * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON + * (i.e. it must be created here with PyMEM_malloc()) */ PyObject *Matrix_CreatePyObject(float *mat, - const unsigned short rowSize, const unsigned short colSize, + const unsigned short row_size, const unsigned short col_size, int type, PyTypeObject *base_type) { MatrixObject *self; - int x, row, col; - /*matrix objects can be any 2-4row x 2-4col matrix*/ - if (rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4) { + /* matrix objects can be any 2-4row x 2-4col matrix */ + if (row_size < 2 || row_size > 4 || col_size < 2 || col_size > 4) { PyErr_SetString(PyExc_RuntimeError, "Matrix(): " "row and column sizes must be between 2 and 4"); @@ -1979,8 +1961,8 @@ PyObject *Matrix_CreatePyObject(float *mat, (MatrixObject *)PyObject_GC_New(MatrixObject, &matrix_Type); if (self) { - self->row_size = rowSize; - self->col_size = colSize; + self->row_size = row_size; + self->col_size = col_size; /* init callbacks as NULL */ self->cb_user= NULL; @@ -1988,36 +1970,29 @@ PyObject *Matrix_CreatePyObject(float *mat, if (type == Py_WRAP) { self->contigPtr = mat; - /*pointer array points to contigous memory*/ - for (x = 0; x < rowSize; x++) { - self->matrix[x] = self->contigPtr + (x * colSize); - } self->wrapped = Py_WRAP; } else if (type == Py_NEW) { - self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float)); + self->contigPtr = PyMem_Malloc(row_size * col_size * sizeof(float)); if (self->contigPtr == NULL) { /*allocation failure*/ PyErr_SetString(PyExc_MemoryError, "Matrix(): " "problem allocating pointer space"); return NULL; } - /*pointer array points to contigous memory*/ - for (x = 0; x < rowSize; x++) { - self->matrix[x] = self->contigPtr + (x * colSize); - } - /*parse*/ + if (mat) { /*if a float array passed*/ - for (row = 0; row < rowSize; row++) { - for (col = 0; col < colSize; col++) { - self->matrix[row][col] = mat[(row * colSize) + col]; - } - } + memcpy(self->contigPtr, mat, row_size * col_size * sizeof(float)); } - else if (rowSize == colSize) { /*or if no arguments are passed return identity matrix for square matrices */ + else if (row_size == col_size) { + /* or if no arguments are passed return identity matrix for square matrices */ PyObject *ret_dummy= Matrix_identity(self); Py_DECREF(ret_dummy); } + else { + /* otherwise zero everything */ + memset(self->contigPtr, 0, row_size * col_size * sizeof(float)); + } self->wrapped = Py_NEW; } else { diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index 6dfcbb1faf9..95768febca0 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h @@ -38,19 +38,33 @@ extern PyTypeObject matrix_Type; #define MatrixObject_Check(_v) PyObject_TypeCheck((_v), &matrix_Type) #define MATRIX_MAX_DIM 4 +/* matrix[row][col] == MATRIX_ITEM_INDEX(matrix, row, col) */ + +#ifdef DEBUG +# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (BLI_assert(_row < (_mat)->row_size && _col < (_mat)->col_size)) +#else +# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0 +#endif + +#define MATRIX_ITEM_INDEX(_mat, _row, _col) (MATRIX_ITEM_ASSERT(_mat, _row, _col),(((_mat)->col_size * (_row)) + (_col))) +#define MATRIX_ITEM_PTR( _mat, _row, _col) ((_mat)->contigPtr + MATRIX_ITEM_INDEX(_mat, _row, _col)) +#define MATRIX_ITEM( _mat, _row, _col) ((_mat)->contigPtr [MATRIX_ITEM_INDEX(_mat, _row, _col)]) + +#define MATRIX_ROW_INDEX(_mat, _row) (MATRIX_ITEM_INDEX(_mat, _row, 0)) +#define MATRIX_ROW_PTR( _mat, _row) ((_mat)->contigPtr + MATRIX_ROW_INDEX(_mat, _row)) + typedef struct { BASE_MATH_MEMBERS(contigPtr); - float *matrix[MATRIX_MAX_DIM]; /* ptr to the contigPtr (accessor) */ unsigned short row_size; unsigned short col_size; } MatrixObject; -/*struct data contains a pointer to the actual data that the -object uses. It can use either PyMem allocated data (which will -be stored in py_data) or be a wrapper for data allocated through -blender (stored in blend_data). This is an either/or struct not both*/ +/* struct data contains a pointer to the actual data that the + * object uses. It can use either PyMem allocated data (which will + * be stored in py_data) or be a wrapper for data allocated through + * blender (stored in blend_data). This is an either/or struct not both */ -/*prototypes*/ +/* prototypes */ PyObject *Matrix_CreatePyObject(float *mat, const unsigned short row_size, const unsigned short col_size, int type, PyTypeObject *base_type); diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index cf817003a98..7ab9b7b0713 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -1039,7 +1039,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) return NULL; - switch(PyTuple_GET_SIZE(args)) { + switch (PyTuple_GET_SIZE(args)) { case 0: break; case 1: @@ -1075,18 +1075,18 @@ static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObjec static void quat__axis_angle_sanitize(float axis[3], float *angle) { if (axis) { - if ( !finite(axis[0]) || - !finite(axis[1]) || - !finite(axis[2])) + if ( !finite(axis[0]) || + !finite(axis[1]) || + !finite(axis[2])) { axis[0]= 1.0f; axis[1]= 0.0f; axis[2]= 0.0f; } - else if ( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && - EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && - EXPP_FloatsAreEqual(axis[2], 0.0f, 10) - ) { + else if ( EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && + EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && + EXPP_FloatsAreEqual(axis[2], 0.0f, 10)) + { axis[0] = 1.0f; } } diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 9d1a22adb12..aedf60e7191 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -54,15 +54,29 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v */ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds)) { - float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + float *vec= NULL; int size= 3; /* default to a 3D vector */ - switch(PyTuple_GET_SIZE(args)) { + switch (PyTuple_GET_SIZE(args)) { case 0: + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } + + fill_vn_fl(vec, size, 0.0f); break; case 1: - if ((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) + if ((size=mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) { + if (vec) { + PyMem_Free(vec); + } return NULL; + } break; default: PyErr_SetString(PyExc_TypeError, @@ -87,6 +101,215 @@ static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *sel } } +/*-----------------------CLASS-METHODS----------------------------*/ +PyDoc_STRVAR(C_Vector_Fill_doc, +".. classmethod:: Fill(size, fill=0.0)\n" +"\n" +" Create a vector of length size with all values set to fill.\n" +"\n" +" :arg size: The length of the vector to be created.\n" +" :type size: int\n" +" :arg fill: The value used to fill the vector.\n" +" :type fill: float\n" +); +static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) +{ + float *vec; + int size; + float fill= 0.0f; + + if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) { + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, + "Vector(): invalid size"); + return NULL; + } + + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Fill(): " + "problem allocating pointer space"); + return NULL; + } + + fill_vn_fl(vec, size, fill); + + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); +} + +PyDoc_STRVAR(C_Vector_Range_doc, +".. classmethod:: Range(start=0, stop, step=1)\n" +"\n" +" Create a filled with a range of values.\n" +"\n" +" :arg start: The start of the range used to fill the vector.\n" +" :type start: int\n" +" :arg stop: The end of the range used to fill the vector.\n" +" :type stop: int\n" +" :arg step: The step between successive values in the vector.\n" +" :type step: int\n" +); +static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) +{ + float *vec; + int stop, size; + int start= 0; + int step= 1; + + if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) { + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 1: + size = start; + start= 0; + break; + case 2: + if (start >= stop) { + PyErr_SetString(PyExc_RuntimeError, + "Start value is larger" + "than the stop value"); + return NULL; + } + + size= stop - start; + break; + default: + if (start >= stop) { + PyErr_SetString(PyExc_RuntimeError, + "Start value is larger" + "than the stop value"); + return NULL; + } + size= (stop - start)/step; + if (size%step) + size++; + break; + } + + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Range(): " + "problem allocating pointer space"); + return NULL; + } + + range_vn_fl(vec, size, (float)start, (float)step); + + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); +} + +PyDoc_STRVAR(C_Vector_Linspace_doc, +".. classmethod:: Linspace(start, stop, size)\n" +"\n" +" Create a vector of the specified size which is filled with linearly spaced values between start and stop values.\n" +"\n" +" :arg start: The start of the range used to fill the vector.\n" +" :type start: int\n" +" :arg stop: The end of the range used to fill the vector.\n" +" :type stop: int\n" +" :arg size: The size of the vector to be created.\n" +" :type size: int\n" +); +static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args) +{ + float *vec; + int size; + float start, end, step; + + if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) { + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, + "Vector.Linspace(): invalid size"); + return NULL; + } + + step= (end - start)/(float)(size-1); + + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Linspace(): " + "problem allocating pointer space"); + return NULL; + } + + range_vn_fl(vec, size, start, step); + + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); +} + +PyDoc_STRVAR(C_Vector_Repeat_doc, +".. classmethod:: Repeat(vector, size)\n" +"\n" +" Create a vector by repeating the values in vector until the required size is reached.\n" +"\n" +" :arg tuple: The vector to draw values from.\n" +" :type tuple: :class:`mathutils.Vector`\n" +" :arg size: The size of the vector to be created.\n" +" :type size: int\n" +); +static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args) +{ + float *vec; + float *iter_vec= NULL; + int i, size, value_size; + PyObject *value; + + if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) { + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, + "Vector.Repeat(): invalid size"); + return NULL; + } + + if ((value_size=mathutils_array_parse_alloc(&iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) { + PyMem_Free(iter_vec); + return NULL; + } + + if (iter_vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Repeat(): " + "problem allocating pointer space"); + return NULL; + } + + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Repeat(): " + "problem allocating pointer space"); + return NULL; + } + + i= 0; + while (i < size) { + vec[i]= iter_vec[i % value_size]; + i++; + } + + PyMem_Free(iter_vec); + + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); +} + /*-----------------------------METHODS---------------------------- */ PyDoc_STRVAR(Vector_zero_doc, ".. method:: zero()\n" @@ -137,6 +360,101 @@ static PyObject *Vector_normalized(VectorObject *self) return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); } +PyDoc_STRVAR(Vector_resize_doc, +".. method:: resize(size=3)\n" +"\n" +" Resize the vector to have size number of elements.\n" +"\n" +" :return: an instance of itself\n" +" :rtype: :class:`Vector`\n" +); +static PyObject *Vector_resize(VectorObject *self, PyObject *value) +{ + int size; + + if (self->wrapped==Py_WRAP) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(): " + "cannot resize wrapped data - only python vectors"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(): " + "cannot resize a vector that has an owner"); + return NULL; + } + + if ((size = PyLong_AsLong(value)) == -1) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(size): " + "expected size argument to be an integer"); + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, + "Vector.resize(): invalid size"); + return NULL; + } + + self->vec = PyMem_Realloc(self->vec, (size * sizeof(float))); + if (self->vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resize(): " + "problem allocating pointer space"); + return NULL; + } + + /* If the vector has increased in length, set all new elements to 0.0f */ + if (size > self->size) { + fill_vn_fl(self->vec + self->size, size - self->size, 0.0f); + } + + self->size = size; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Vector_resized_doc, +".. method:: resized(size=3)\n" +"\n" +" Return a resized copy of the vector with size number of elements.\n" +"\n" +" :return: a new vector\n" +" :rtype: :class:`Vector`\n" +); +static PyObject *Vector_resized(VectorObject *self, PyObject *value) +{ + int size; + float *vec; + + /*if (!PyArg_ParseTuple(args, "i:resize", &size)) + return NULL;*/ + if ((size = PyLong_AsLong(value)) == -1) { + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, + "Vector.resized(): invalid size"); + return NULL; + } + + vec= PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resized(): " + "problem allocating pointer space"); + return NULL; + } + + fill_vn_fl(vec, size, 0.0f); + memcpy(vec, self->vec, self->size * sizeof(float)); + + return Vector_CreatePyObject_alloc(vec, size, NULL); +} + PyDoc_STRVAR(Vector_resize_2d_doc, ".. method:: resize_2d()\n" "\n" @@ -394,7 +712,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) if (strlen(strack) == 2) { if (strack[0] == '-') { - switch(strack[1]) { + switch (strack[1]) { case 'X': track = 3; break; @@ -415,7 +733,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) } } else if (strlen(strack) == 1) { - switch(strack[0]) { + switch (strack[0]) { case '-': case 'X': track = 0; @@ -440,7 +758,7 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) if (sup) { const char *axis_err_msg= "only X, Y or Z for up axis"; if (strlen(sup) == 1) { - switch(*sup) { + switch (*sup) { case 'X': up = 0; break; @@ -505,6 +823,12 @@ static PyObject *Vector_reflect(VectorObject *self, PyObject *value) if ((value_size= mathutils_array_parse(tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) return NULL; + if (self->size < 2 || self->size > 4) { + PyErr_SetString(PyExc_ValueError, + "Vector must be 2D, 3D or 4D"); + return NULL; + } + mirror[0] = tvec[0]; mirror[1] = tvec[1]; if (value_size > 2) mirror[2] = tvec[2]; @@ -544,6 +868,12 @@ static PyObject *Vector_cross(VectorObject *self, PyObject *value) if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) return NULL; + if (self->size != 3) { + PyErr_SetString(PyExc_ValueError, + "Vector must be 3D"); + return NULL; + } + ret= (VectorObject *)Vector_CreatePyObject(NULL, 3, Py_NEW, Py_TYPE(self)); cross_v3_v3v3(ret->vec, self->vec, tvec); return (PyObject *)ret; @@ -561,15 +891,20 @@ PyDoc_STRVAR(Vector_dot_doc, ); static PyObject *Vector_dot(VectorObject *self, PyObject *value) { - float tvec[MAX_DIMENSIONS]; + float *tvec; if (BaseMath_ReadCallback(self) == -1) return NULL; - if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) - return NULL; + if (mathutils_array_parse_alloc(&tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) { + goto cleanup; + } return PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size)); + +cleanup: + PyMem_Free(tvec); + return NULL; } PyDoc_STRVAR(Vector_angle_doc, @@ -607,6 +942,12 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args) if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) return NULL; + if (self->size > 4) { + PyErr_SetString(PyExc_ValueError, + "Vector must be 2D, 3D or 4D"); + return NULL; + } + for (x = 0; x < size; x++) { dot_self += (double)self->vec[x] * (double)self->vec[x]; dot_other += (double)tvec[x] * (double)tvec[x]; @@ -647,7 +988,7 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value) { float quat[4], vec_a[3], vec_b[3]; - if (self->size < 3) { + if (self->size < 3 || self->size > 4) { PyErr_SetString(PyExc_ValueError, "vec.difference(value): " "expects both vectors to be size 3 or 4"); @@ -692,6 +1033,12 @@ static PyObject *Vector_project(VectorObject *self, PyObject *value) if (mathutils_array_parse(tvec, size, size, value, "Vector.project(other), invalid 'other' arg") == -1) return NULL; + if (self->size > 4) { + PyErr_SetString(PyExc_ValueError, + "Vector must be 2D, 3D or 4D"); + return NULL; + } + if (BaseMath_ReadCallback(self) == -1) return NULL; @@ -725,24 +1072,41 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args) const int size= self->size; PyObject *value= NULL; float fac, ifac; - float tvec[MAX_DIMENSIONS], vec[MAX_DIMENSIONS]; + float *tvec, *vec; int x; if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) return NULL; - if (mathutils_array_parse(tvec, size, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) - return NULL; + if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) { + goto cleanup; + } - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback(self) == -1) { + goto cleanup; + } + + vec= PyMem_Malloc(size * sizeof(float)); + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.lerp(): " + "problem allocating pointer space"); return NULL; + } ifac= 1.0f - fac; for (x = 0; x < size; x++) { vec[x] = (ifac * self->vec[x]) + (fac * tvec[x]); } - return Vector_CreatePyObject(vec, size, Py_NEW, Py_TYPE(self)); + + PyMem_Free(tvec); + + return Vector_CreatePyObject_alloc(vec, size, Py_TYPE(self)); + +cleanup: + PyMem_Free(tvec); + return NULL; } PyDoc_STRVAR(Vector_rotate_doc, @@ -763,7 +1127,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value) if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) return NULL; - if (self->size < 3) { + if (self->size < 3 || self->size > 4) { PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); return NULL; @@ -903,8 +1267,8 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end) /* sequence slice (set): vector[a:b] = value */ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) { - int y, size = 0; - float vec[MAX_DIMENSIONS]; + int size = 0; + float *vec= NULL; if (BaseMath_ReadCallback(self) == -1) return -1; @@ -914,18 +1278,30 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se begin = MIN2(begin, end); size = (end - begin); - if (mathutils_array_parse(vec, size, size, seq, "vector[begin:end] = [...]") == -1) + if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) { + goto cleanup; + } + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "vec[:] = seq: " + "problem allocating pointer space"); return -1; + } /*parsed well - now set in vector*/ - for (y = 0; y < size; y++) { - self->vec[begin + y] = vec[y]; - } + memcpy(self->vec + begin, vec, size * sizeof(float)); if (BaseMath_WriteCallback(self) == -1) return -1; + PyMem_Free(vec); + return 0; + +cleanup: + PyMem_Free(vec); + return -1; } /* Numeric Protocols */ @@ -933,7 +1309,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se static PyObject *Vector_add(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; - float vec[MAX_DIMENSIONS]; + float *vec= NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { PyErr_Format(PyExc_AttributeError, @@ -956,9 +1332,18 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2) return NULL; } + vec= PyMem_Malloc(vec1->size * sizeof(float)); + + if (vec == NULL) { /*allocation failure*/ + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } + add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); - return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); } /* addition in-place: obj += obj */ @@ -997,7 +1382,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) static PyObject *Vector_sub(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; - float vec[MAX_DIMENSIONS]; + float *vec; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { PyErr_Format(PyExc_AttributeError, @@ -1019,9 +1404,18 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) return NULL; } + vec= PyMem_Malloc(vec1->size * sizeof(float)); + + if (vec == NULL) { /*allocation failure*/ + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } + sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); - return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); } /* subtraction in-place: obj -= obj */ @@ -1093,7 +1487,7 @@ int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, for (x = 0; x < mat->col_size; x++) { for (y = 0; y < mat->row_size; y++) { - dot += (double)(mat->matrix[y][x] * vec_cpy[y]); + dot += (double)(MATRIX_ITEM(mat, y, x) * vec_cpy[y]); } rvec[z++] = (float)dot; dot = 0.0f; @@ -1104,9 +1498,18 @@ int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, static PyObject *vector_mul_float(VectorObject *vec, const float scalar) { - float tvec[MAX_DIMENSIONS]; + float *tvec= NULL; + tvec= PyMem_Malloc(vec->size * sizeof(float)); + + if (tvec == NULL) { /*allocation failure*/ + PyErr_SetString(PyExc_MemoryError, + "vec * float: " + "problem allocating pointer space"); + return NULL; + } + mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar); - return Vector_CreatePyObject(tvec, vec->size, Py_NEW, Py_TYPE(vec)); + return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec)); } static PyObject *Vector_mul(PyObject *v1, PyObject *v2) @@ -1277,8 +1680,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) /* divid: obj / obj */ static PyObject *Vector_div(PyObject *v1, PyObject *v2) { - int i; - float vec[4], scalar; + float *vec= NULL, scalar; VectorObject *vec1 = NULL; if (!VectorObject_Check(v1)) { /* not a vector */ @@ -1287,7 +1689,7 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) "Vector must be divided by a float"); return NULL; } - vec1 = (VectorObject*)v1; /* vector */ + vec1 = (VectorObject *)v1; /* vector */ if (BaseMath_ReadCallback(vec1) == -1) return NULL; @@ -1306,16 +1708,23 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) return NULL; } - for (i = 0; i < vec1->size; i++) { - vec[i] = vec1->vec[i] / scalar; + vec= PyMem_Malloc(vec1->size * sizeof(float)); + + if (vec == NULL) { /*allocation failure*/ + PyErr_SetString(PyExc_MemoryError, + "vec / value: " + "problem allocating pointer space"); + return NULL; } - return Vector_CreatePyObject(vec, vec1->size, Py_NEW, Py_TYPE(v1)); + + mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f/scalar); + + return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); } /* divide in-place: obj /= obj */ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) { - int i; float scalar; VectorObject *vec1 = (VectorObject*)v1; @@ -1335,9 +1744,8 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) "divide by zero error"); return NULL; } - for (i = 0; i < vec1->size; i++) { - vec1->vec[i] /= scalar; - } + + mul_vn_fl(vec1->vec, vec1->size, 1.0f/scalar); (void)BaseMath_WriteCallback(vec1); @@ -1349,29 +1757,24 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) returns the negative of this object*/ static PyObject *Vector_neg(VectorObject *self) { - float tvec[MAX_DIMENSIONS]; + float *tvec; if (BaseMath_ReadCallback(self) == -1) return NULL; + tvec= PyMem_Malloc(self->size * sizeof(float)); negate_vn_vn(tvec, self->vec, self->size); - return Vector_CreatePyObject(tvec, self->size, Py_NEW, Py_TYPE(self)); + return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self)); } /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ static double vec_magnitude_nosqrt(float *data, int size) { - double dot = 0.0f; - int i; - - for (i=0; i<size; i++) { - dot += (double)data[i]; - } /*return (double)sqrt(dot);*/ /* warning, line above removed because we are not using the length, rather the comparing the sizes and for this we do not need the sqrt for the actual length, the dot must be sqrt'd */ - return dot; + return dot_vn_vn(data, data, size); } @@ -1606,16 +2009,10 @@ static int Vector_setAxis(VectorObject *self, PyObject *value, void *type) /* vector.length */ static PyObject *Vector_getLength(VectorObject *self, void *UNUSED(closure)) { - double dot = 0.0f; - int i; - if (BaseMath_ReadCallback(self) == -1) return NULL; - for (i = 0; i < self->size; i++) { - dot += (double)(self->vec[i] * self->vec[i]); - } - return PyFloat_FromDouble(sqrt(dot)); + return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size))); } static int Vector_setLength(VectorObject *self, PyObject *value) @@ -2213,7 +2610,7 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v //muliplication for (x = 0; x < mat->row_size; x++) { for (y = 0; y < mat->col_size; y++) { - dot += mat->matrix[x][y] * vec_cpy[y]; + dot += MATRIX_ITEM(mat, x, y) * vec_cpy[y]; } rvec[z++] = (float)dot; dot = 0.0f; @@ -2242,6 +2639,12 @@ static PyObject *Vector_negate(VectorObject *self) } static struct PyMethodDef Vector_methods[] = { + /* Class Methods */ + {"Fill", (PyCFunction) C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc}, + {"Range", (PyCFunction) C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc}, + {"Linspace", (PyCFunction) C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc}, + {"Repeat", (PyCFunction) C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc}, + /* in place only */ {"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc}, {"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc}, @@ -2250,6 +2653,8 @@ static struct PyMethodDef Vector_methods[] = { {"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc}, {"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc}, + {"resize", (PyCFunction) Vector_resize, METH_O, Vector_resize_doc}, + {"resized", (PyCFunction) Vector_resized, METH_O, Vector_resized_doc}, {"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc}, {"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc}, {"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc}, @@ -2375,7 +2780,7 @@ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTy { VectorObject *self; - if (size > 4 || size < 2) { + if (size < 2) { PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); return NULL; @@ -2429,3 +2834,12 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, int cb_type, int return (PyObject *)self; } + +PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type) +{ + VectorObject *vect_ob; + vect_ob= (VectorObject *)Vector_CreatePyObject(vec, size, Py_WRAP, base_type); + vect_ob->wrapped= Py_NEW; + + return (PyObject *)vect_ob; +} diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index 0f7fa174d18..4e10e795602 100644 --- a/source/blender/python/mathutils/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h @@ -41,11 +41,12 @@ extern PyTypeObject vector_Type; typedef struct { BASE_MATH_MEMBERS(vec); - unsigned char size; /* vec size 2,3 or 4 */ + int size; /* vec size 2,3 or 4 */ } VectorObject; /*prototypes*/ PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type); PyObject *Vector_CreatePyObject_cb(PyObject *user, int size, int callback_type, int subtype); +PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type); #endif /* MATHUTILS_VECTOR_H */ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index d3b6e2e8b29..f3a843baf66 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -99,11 +99,11 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject* return NULL; } - if ( BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1 || - BaseMath_ReadCallback(ray) == -1 || - BaseMath_ReadCallback(ray_off) == -1) + if ( BaseMath_ReadCallback(vec1) == -1 || + BaseMath_ReadCallback(vec2) == -1 || + BaseMath_ReadCallback(vec3) == -1 || + BaseMath_ReadCallback(ray) == -1 || + BaseMath_ReadCallback(ray_off) == -1) { return NULL; } @@ -199,10 +199,10 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject return NULL; } - if ( BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1 || - BaseMath_ReadCallback(vec4) == -1) + if ( BaseMath_ReadCallback(vec1) == -1 || + BaseMath_ReadCallback(vec2) == -1 || + BaseMath_ReadCallback(vec3) == -1 || + BaseMath_ReadCallback(vec4) == -1) { return NULL; } @@ -298,9 +298,9 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args) return NULL; } - if ( BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1) + if ( BaseMath_ReadCallback(vec1) == -1 || + BaseMath_ReadCallback(vec2) == -1 || + BaseMath_ReadCallback(vec3) == -1) { return NULL; } @@ -327,10 +327,10 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args) return NULL; } - if ( BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1 || - BaseMath_ReadCallback(vec4) == -1) + if ( BaseMath_ReadCallback(vec1) == -1 || + BaseMath_ReadCallback(vec2) == -1 || + BaseMath_ReadCallback(vec3) == -1 || + BaseMath_ReadCallback(vec4) == -1) { return NULL; } @@ -374,9 +374,9 @@ static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args) return NULL; } - if ( BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1) + if ( BaseMath_ReadCallback(vec1) == -1 || + BaseMath_ReadCallback(vec2) == -1 || + BaseMath_ReadCallback(vec3) == -1) { return NULL; } @@ -424,10 +424,10 @@ static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObj return NULL; } - if ( BaseMath_ReadCallback(line_a1) == -1 || - BaseMath_ReadCallback(line_a2) == -1 || - BaseMath_ReadCallback(line_b1) == -1 || - BaseMath_ReadCallback(line_b2) == -1) + if ( BaseMath_ReadCallback(line_a1) == -1 || + BaseMath_ReadCallback(line_a2) == -1 || + BaseMath_ReadCallback(line_b1) == -1 || + BaseMath_ReadCallback(line_b2) == -1) { return NULL; } @@ -474,10 +474,10 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec return NULL; } - if ( BaseMath_ReadCallback(line_a) == -1 || - BaseMath_ReadCallback(line_b) == -1 || - BaseMath_ReadCallback(plane_co) == -1 || - BaseMath_ReadCallback(plane_no) == -1) + if ( BaseMath_ReadCallback(line_a) == -1 || + BaseMath_ReadCallback(line_b) == -1 || + BaseMath_ReadCallback(plane_co) == -1 || + BaseMath_ReadCallback(plane_no) == -1) { return NULL; } @@ -530,10 +530,10 @@ static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObje return NULL; } - if ( BaseMath_ReadCallback(plane_a_co) == -1 || - BaseMath_ReadCallback(plane_a_no) == -1 || - BaseMath_ReadCallback(plane_b_co) == -1 || - BaseMath_ReadCallback(plane_b_no) == -1) + if ( BaseMath_ReadCallback(plane_a_co) == -1 || + BaseMath_ReadCallback(plane_a_no) == -1 || + BaseMath_ReadCallback(plane_b_co) == -1 || + BaseMath_ReadCallback(plane_b_no) == -1) { return NULL; } @@ -592,9 +592,9 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje return NULL; } - if ( BaseMath_ReadCallback(line_a) == -1 || - BaseMath_ReadCallback(line_b) == -1 || - BaseMath_ReadCallback(sphere_co) == -1) + if ( BaseMath_ReadCallback(line_a) == -1 || + BaseMath_ReadCallback(line_b) == -1 || + BaseMath_ReadCallback(sphere_co) == -1) { return NULL; } @@ -612,7 +612,7 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje PyObject *ret= PyTuple_New(2); - switch(isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { + switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { case 1: if (!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; use_b= FALSE; @@ -672,9 +672,9 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO return NULL; } - if ( BaseMath_ReadCallback(line_a) == -1 || - BaseMath_ReadCallback(line_b) == -1 || - BaseMath_ReadCallback(sphere_co) == -1) + if ( BaseMath_ReadCallback(line_a) == -1 || + BaseMath_ReadCallback(line_b) == -1 || + BaseMath_ReadCallback(sphere_co) == -1) { return NULL; } @@ -685,7 +685,7 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO PyObject *ret= PyTuple_New(2); - switch(isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { + switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { case 1: if (!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; use_b= FALSE; @@ -737,9 +737,9 @@ static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObjec return NULL; } - if ( BaseMath_ReadCallback(pt) == -1 || - BaseMath_ReadCallback(line_1) == -1 || - BaseMath_ReadCallback(line_2) == -1) + if ( BaseMath_ReadCallback(pt) == -1 || + BaseMath_ReadCallback(line_1) == -1 || + BaseMath_ReadCallback(line_2) == -1) { return NULL; } @@ -791,10 +791,10 @@ static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObj return NULL; } - if ( BaseMath_ReadCallback(pt_vec) == -1 || - BaseMath_ReadCallback(tri_p1) == -1 || - BaseMath_ReadCallback(tri_p2) == -1 || - BaseMath_ReadCallback(tri_p3) == -1) + if ( BaseMath_ReadCallback(pt_vec) == -1 || + BaseMath_ReadCallback(tri_p1) == -1 || + BaseMath_ReadCallback(tri_p2) == -1 || + BaseMath_ReadCallback(tri_p3) == -1) { return NULL; } @@ -834,11 +834,11 @@ static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyOb return NULL; } - if ( BaseMath_ReadCallback(pt_vec) == -1 || - BaseMath_ReadCallback(quad_p1) == -1 || - BaseMath_ReadCallback(quad_p2) == -1 || - BaseMath_ReadCallback(quad_p3) == -1 || - BaseMath_ReadCallback(quad_p4) == -1) + if ( BaseMath_ReadCallback(pt_vec) == -1 || + BaseMath_ReadCallback(quad_p1) == -1 || + BaseMath_ReadCallback(quad_p2) == -1 || + BaseMath_ReadCallback(quad_p3) == -1 || + BaseMath_ReadCallback(quad_p4) == -1) { return NULL; } @@ -872,9 +872,9 @@ static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyOb return NULL; } - if ( BaseMath_ReadCallback(pt) == -1 || - BaseMath_ReadCallback(plene_co) == -1 || - BaseMath_ReadCallback(plane_no) == -1) + if ( BaseMath_ReadCallback(pt) == -1 || + BaseMath_ReadCallback(plene_co) == -1 || + BaseMath_ReadCallback(plane_no) == -1) { return NULL; } @@ -993,10 +993,10 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* return NULL; } - if ( BaseMath_ReadCallback(vec_k1) == -1 || - BaseMath_ReadCallback(vec_h1) == -1 || - BaseMath_ReadCallback(vec_k2) == -1 || - BaseMath_ReadCallback(vec_h2) == -1) + if ( BaseMath_ReadCallback(vec_k1) == -1 || + BaseMath_ReadCallback(vec_h1) == -1 || + BaseMath_ReadCallback(vec_k2) == -1 || + BaseMath_ReadCallback(vec_h2) == -1) { return NULL; } diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index 09337d9a23b..c0e8ac24baa 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -201,7 +201,7 @@ static void rand_vn(float *array_tar, const int size) { float *array_pt= array_tar + (size-1); int i= size; - while(i--) { *(array_pt--) = 2.0f * frand() - 1.0f; } + while (i--) { *(array_pt--) = 2.0f * frand() - 1.0f; } } /* Fills an array of length 3 with noise values */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index a11bd6e9a68..0cc0d79b292 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -177,7 +177,6 @@ void WM_init(bContext *C, int argc, const char **argv) GPU_extensions_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); GPU_set_anisotropic(U.anisotropic_filter); - GPU_code_generate_glsl_lib(); UI_init(); } |