diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
74 files changed, 19787 insertions, 13403 deletions
diff --git a/source/blender/blenkernel/intern/BME_conversions.c b/source/blender/blenkernel/intern/BME_conversions.c index 39af580969f..177bb4a136b 100644 --- a/source/blender/blenkernel/intern/BME_conversions.c +++ b/source/blender/blenkernel/intern/BME_conversions.c @@ -50,11 +50,13 @@ #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_edgehash.h" -#include "BIF_editmesh.h" -#include "editmesh.h" +//XXX #include "BIF_editmesh.h" +//XXX #include "editmesh.h" #include "bmesh_private.h" -#include "BSE_edit.h" +//XXX #include "BSE_edit.h" + +/* XXX IMPORTANT: editmesh stuff doesn't belong in kernel! (ton) */ /*merge these functions*/ static void BME_DMcorners_to_loops(BME_Mesh *bm, CustomData *facedata, int index, BME_Poly *f, int numCol, int numTex){ @@ -302,7 +304,7 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { e->flag = eed->f & SELECT; if(eed->sharp) e->flag |= ME_SHARP; if(eed->seam) e->flag |= ME_SEAM; - if(eed->h & EM_FGON) e->flag |= ME_FGON; + //XXX if(eed->h & EM_FGON) e->flag |= ME_FGON; if(eed->h & 1) e->flag |= ME_HIDE; eed->tmp.e = (EditEdge*)e; CustomData_bmesh_copy_data(&em->edata, &bm->edata, eed->data, &e->data); @@ -343,26 +345,22 @@ BME_Mesh *BME_editmesh_to_bmesh(EditMesh *em) { BME_model_end(bm); return bm; } -/* adds the geometry in the bmesh to G.editMesh (does not free G.editMesh) +/* adds the geometry in the bmesh to editMesh (does not free editMesh) * if td != NULL, the transdata will be mapped to the EditVert's co */ -EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { +void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) { BME_Vert *v1; BME_Edge *e; BME_Poly *f; BME_TransData *vtd; - EditMesh *em; EditVert *eve1, *eve2, *eve3, *eve4, **evlist; EditEdge *eed; EditFace *efa; int totvert, len, i, numTex, numCol; - em = G.editMesh; - - if (em == NULL) return NULL; - + if (em == NULL) return; CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -378,7 +376,7 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist"); for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) { v1->tflag1 = i; - eve1 = addvertlist(v1->co,NULL); + eve1 = NULL; //XXX addvertlist(v1->co,NULL); if (td && (vtd = BME_get_transdata(td,v1))) { vtd->loc = eve1->co; } @@ -392,17 +390,17 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { /* make edges */ for (e=bm->edges.first;e;e=e->next) { - if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){ - eed= addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL); + if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){ + eed= NULL; //XXX addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL); eed->crease = e->crease; eed->bweight = e->bweight; if(e->flag & ME_SEAM) eed->seam = 1; if(e->flag & ME_SHARP) eed->sharp = 1; if(e->flag & SELECT) eed->f |= SELECT; - if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! + //XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! if(e->flag & ME_HIDE) eed->h |= 1; - if(G.scene->selectmode==SCE_SELECT_EDGE) - EM_select_edge(eed, eed->f & SELECT); + if(em->selectmode==SCE_SELECT_EDGE) + ; //XXX EM_select_edge(eed, eed->f & SELECT); CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data); } @@ -422,15 +420,16 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { eve4= NULL; } - efa = addfacelist(eve1, eve2, eve3, eve4, NULL, NULL); + efa = NULL; //XXX addfacelist(eve1, eve2, eve3, eve4, NULL, NULL); efa->mat_nr = (unsigned char)f->mat_nr; efa->flag= f->flag & ~ME_HIDE; if(f->flag & ME_FACE_SEL) { efa->f |= SELECT; } if(f->flag & ME_HIDE) efa->h= 1; - if((G.f & G_FACESELECT) && (efa->f & SELECT)) - EM_select_face(efa, 1); /* flush down */ + // XXX flag depricated + // if((G.f & G_FACESELECT) && (efa->f & SELECT)) + //XXX EM_select_face(efa, 1); /* flush down */ CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data); BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex); } @@ -438,9 +437,6 @@ EditMesh *BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td) { MEM_freeN(evlist); - countall(); - - return em; } /* Adds the geometry found in dm to bm diff --git a/source/blender/blenkernel/intern/BME_tools.c b/source/blender/blenkernel/intern/BME_tools.c index f3e4add34e9..a41307de183 100644 --- a/source/blender/blenkernel/intern/BME_tools.c +++ b/source/blender/blenkernel/intern/BME_tools.c @@ -38,14 +38,13 @@ #include "DNA_listBase.h" #include "DNA_meshdata_types.h" #include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "BKE_utildefines.h" #include "BKE_bmesh.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "blendef.h" - /*split this all into a seperate bevel.c file in src*/ /* ------- Bevel code starts here -------- */ @@ -206,6 +205,7 @@ static BME_Poly *BME_split_face(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Ver } +#if 0 static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, float fac) { void *src[2]; @@ -218,6 +218,7 @@ static void BME_data_interp_from_verts(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, CustomData_bmesh_interp(&bm->vdata, src, w, NULL, 2, v->data); } } +#endif static void BME_data_facevert_edgesplit(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Vert *v, BME_Edge *e1, float fac){ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d43cbdebe72..bc6e549dc6f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -71,7 +71,6 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_object.h" #include "BKE_subsurf.h" #include "BKE_texture.h" @@ -81,10 +80,6 @@ #include "BLO_sys_types.h" // for intptr_t support -#ifdef WITH_VERSE -#include "BKE_verse.h" -#endif - #include "BIF_gl.h" #include "BIF_glutil.h" @@ -909,7 +904,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, glShadeModel(GL_SMOOTH); for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (long) i++; + eve->tmp.l = (intptr_t) i++; #define PASSATTRIB(efa, eve, vert) { \ if(attribs.totorco) { \ @@ -1391,581 +1386,16 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, return (DerivedMesh*) emdm; } -#ifdef WITH_VERSE - -/* verse derived mesh */ -typedef struct { - struct DerivedMesh dm; - struct VNode *vnode; - struct VLayer *vertex_layer; - struct VLayer *polygon_layer; - struct ListBase *edges; - float (*vertexCos)[3]; -} VDerivedMesh; - -/* this function set up border points of verse mesh bounding box */ -static void vDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert; - - if(!vdm->vertex_layer) return; - - vvert = (VerseVert*)vdm->vertex_layer->dl.lb.first; - - if(vdm->vertex_layer->dl.da.count > 0) { - while(vvert) { - DO_MINMAX(vdm->vertexCos ? vvert->cos : vvert->co, min_r, max_r); - vvert = vvert->next; - } - } - else { - min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0; - } -} - -/* this function return number of vertexes in vertex layer */ -static int vDM_getNumVerts(DerivedMesh *dm) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - - if(!vdm->vertex_layer) return 0; - else return vdm->vertex_layer->dl.da.count; -} - -/* this function return number of 'fake' edges */ -static int vDM_getNumEdges(DerivedMesh *dm) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - - return BLI_countlist(vdm->edges); -} - -/* this function returns number of polygons in polygon layer */ -static int vDM_getNumFaces(DerivedMesh *dm) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - - if(!vdm->polygon_layer) return 0; - else return vdm->polygon_layer->dl.da.count; -} - -/* this function doesn't return vertex with index of access array, - * but it return 'indexth' vertex of dynamic list */ -void vDM_getVert(DerivedMesh *dm, int index, MVert *vert_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert; - int i; - - if(!vdm->vertex_layer) return; - - for(vvert = vdm->vertex_layer->dl.lb.first, i=0 ; i<index; i++) vvert = vvert->next; - - if(vvert) { - VECCOPY(vert_r->co, vvert->co); - - vert_r->no[0] = vvert->no[0] * 32767.0; - vert_r->no[1] = vvert->no[1] * 32767.0; - vert_r->no[2] = vvert->no[2] * 32767.0; - - /* TODO what to do with vert_r->flag and vert_r->mat_nr? */ - vert_r->mat_nr = 0; - vert_r->flag = 0; - } -} - -/* this function returns fake verse edge */ -void vDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseEdge *vedge; - struct VLayer *vert_vlayer = vdm->vertex_layer; - struct VerseVert *vvert; - int j; - - if(!vdm->vertex_layer || !vdm->edges) return; - - if(vdm->edges->first) { - struct VerseVert *vvert1, *vvert2; - - /* store vert indices in tmp union */ - for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, j++) - vvert->tmp.index = j; - - for(vedge = vdm->edges->first; vedge; vedge = vedge->next) { - if(vedge->tmp.index==index) { - vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0); - vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1); - - if(vvert1 && vvert2) { - edge_r->v1 = vvert1->tmp.index; - edge_r->v2 = vvert2->tmp.index; - } - else { - edge_r->v1 = 0; - edge_r->v2 = 0; - } - /* not supported yet */ - edge_r->flag = 0; - edge_r->crease = 0; - edge_r->bweight = 0; - break; - } - } - } -} - -/* this function doesn't return face with index of access array, - * but it returns 'indexth' vertex of dynamic list */ -void vDM_getFace(DerivedMesh *dm, int index, MFace *face_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseFace *vface; - struct VerseVert *vvert; - struct VerseVert *vvert0, *vvert1, *vvert2, *vvert3; - int i; - - if(!vdm->vertex_layer || !vdm->polygon_layer) return; - - for(vface = vdm->polygon_layer->dl.lb.first, i = 0; i < index; ++i) vface = vface->next; - - face_r->mat_nr = 0; - face_r->flag = 0; - - /* goddamn, we have to search all verts to find indices */ - vvert0 = vface->vvert0; - vvert1 = vface->vvert1; - vvert2 = vface->vvert2; - vvert3 = vface->vvert3; - if(!vvert3) face_r->v4 = 0; - - for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert0 || vvert1 || vvert2 || vvert3; i++, vvert = vvert->next) { - if(vvert == vvert0) { - face_r->v1 = i; - vvert0 = NULL; - } - if(vvert == vvert1) { - face_r->v2 = i; - vvert1 = NULL; - } - if(vvert == vvert2) { - face_r->v3 = i; - vvert2 = NULL; - } - if(vvert == vvert3) { - face_r->v4 = i; - vvert3 = NULL; - } - } - - test_index_face(face_r, NULL, 0, vface->vvert3?4:3); -} - -/* fill array of mvert */ -void vDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert; - - if(!vdm->vertex_layer) return; - - for(vvert = vdm->vertex_layer->dl.lb.first ; vvert; vvert = vvert->next, ++vert_r) { - VECCOPY(vert_r->co, vvert->co); - - vert_r->no[0] = vvert->no[0] * 32767.0; - vert_r->no[1] = vvert->no[1] * 32767.0; - vert_r->no[2] = vvert->no[2] * 32767.0; - - vert_r->mat_nr = 0; - vert_r->flag = 0; - } -} - -/* dummy function, edges arent supported in verse mesh */ -void vDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - - if(!vdm->vertex_layer || !vdm->edges) return; - - if(vdm->edges->first) { - struct VerseEdge *vedge; - struct VLayer *vert_vlayer = vdm->vertex_layer; - struct VerseVert *vvert, *vvert1, *vvert2; - int j; - - /* store vert indices in tmp union */ - for(vvert = vdm->vertex_layer->dl.lb.first, j = 0; vvert; vvert = vvert->next, ++j) - vvert->tmp.index = j; - - for(vedge = vdm->edges->first, j=0 ; vedge; vedge = vedge->next, ++edge_r, j++) { - /* create temporary edge index */ - vedge->tmp.index = j; - vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0); - vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1); - if(vvert1 && vvert2) { - edge_r->v1 = vvert1->tmp.index; - edge_r->v2 = vvert2->tmp.index; - } - else { - printf("error: vDM_copyEdgeArray: %d, %d\n", vedge->v0, vedge->v1); - edge_r->v1 = 0; - edge_r->v2 = 0; - } - /* not supported yet */ - edge_r->flag = 0; - edge_r->crease = 0; - edge_r->bweight = 0; - } - } -} - -/* fill array of mfaces */ -void vDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseFace *vface; - struct VerseVert *vvert; - int i; - - if(!vdm->vertex_layer || !vdm->polygon_layer) return; - - /* store vertexes indices in tmp union */ - for(vvert = vdm->vertex_layer->dl.lb.first, i = 0; vvert; vvert = vvert->next, ++i) - vvert->tmp.index = i; - - for(vface = vdm->polygon_layer->dl.lb.first; vface; vface = vface->next, ++face_r) { - face_r->mat_nr = 0; - face_r->flag = 0; - - face_r->v1 = vface->vvert0->tmp.index; - face_r->v2 = vface->vvert1->tmp.index; - face_r->v3 = vface->vvert2->tmp.index; - if(vface->vvert3) face_r->v4 = vface->vvert3->tmp.index; - else face_r->v4 = 0; - - test_index_face(face_r, NULL, 0, vface->vvert3?4:3); - } -} - -/* return coordination of vertex with index */ -static void vDM_getVertCo(DerivedMesh *dm, int index, float co_r[3]) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert = NULL; - - if(!vdm->vertex_layer) return; - - vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index); - - if(vvert) { - VECCOPY(co_r, vdm->vertexCos ? vvert->cos : vvert->co); - } - else { - co_r[0] = co_r[1] = co_r[2] = 0.0; - } -} - -/* return array of vertex coordiantions */ -static void vDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3]) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert; - int i = 0; - - if(!vdm->vertex_layer) return; - - vvert = vdm->vertex_layer->dl.lb.first; - while(vvert) { - VECCOPY(cos_r[i], vdm->vertexCos ? vvert->cos : vvert->co); - i++; - vvert = vvert->next; - } -} - -/* return normal of vertex with index */ -static void vDM_getVertNo(DerivedMesh *dm, int index, float no_r[3]) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert = NULL; - - if(!vdm->vertex_layer) return; - - vvert = BLI_dlist_find_link(&(vdm->vertex_layer->dl), index); - if(vvert) { - VECCOPY(no_r, vvert->no); - } - else { - no_r[0] = no_r[1] = no_r[2] = 0.0; - } -} - -/* draw all VerseVertexes */ -static void vDM_drawVerts(DerivedMesh *dm) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseVert *vvert; - - if(!vdm->vertex_layer) return; - - vvert = vdm->vertex_layer->dl.lb.first; - - bglBegin(GL_POINTS); - while(vvert) { - bglVertex3fv(vdm->vertexCos ? vvert->cos : vvert->co); - vvert = vvert->next; - } - bglEnd(); -} - -/* draw all edges of VerseFaces ... it isn't optimal, because verse - * specification doesn't support edges :-( ... bother eskil ;-) - * ... some edges (most of edges) are drawn twice */ -static void vDM_drawEdges(DerivedMesh *dm, int drawLooseEdges) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseEdge *vedge; - struct VLayer *vert_vlayer = vdm->vertex_layer; - - if(vert_vlayer && vdm->edges && (BLI_countlist(vdm->edges) > 0)) { - struct VerseVert *vvert1, *vvert2; - - glBegin(GL_LINES); - for(vedge = vdm->edges->first; vedge; vedge = vedge->next) { - vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v0); - vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vedge->v1); - if(vvert1 && vvert2) { - glVertex3fv(vdm->vertexCos ? vvert1->cos : vvert1->co); - glVertex3fv(vdm->vertexCos ? vvert2->cos : vvert2->co); - } - } - glEnd(); - } -} - -/* verse spec doesn't support edges ... loose edges can't exist */ -void vDM_drawLooseEdges(DerivedMesh *dm) -{ -} - -/* draw uv edges, not supported yet */ -static void vDM_drawUVEdges(DerivedMesh *dm) -{ -} - -/* draw all VerseFaces */ -static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseFace *vface; - - if(!vdm->polygon_layer) return; - - vface = vdm->polygon_layer->dl.lb.first; - - glShadeModel(GL_FLAT); - while(vface) { - glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES); - glNormal3fv(vface->no); - glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co); - glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co); - glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co); - if(vface->vvert3) - glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co); - glEnd(); - vface = vface->next; - } -} - -/* this function should draw mesh with mapped texture, but it isn't supported yet */ -static void vDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, MCol *mcol, int matnr)) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseFace *vface; - - if(!vdm->polygon_layer) return; - - vface = vdm->polygon_layer->dl.lb.first; - - while(vface) { - glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES); - glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co); - glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co); - glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co); - if(vface->vvert3) - glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co); - glEnd(); - - vface = vface->next; - } -} - -/* this function should draw mesh with colored faces (weight paint, vertex - * colors, etc.), but it isn't supported yet */ -static void vDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - struct VerseFace *vface; - - if(!vdm->polygon_layer) return; - - vface = vdm->polygon_layer->dl.lb.first; - - while(vface) { - glBegin(vface->vvert3?GL_QUADS:GL_TRIANGLES); - glVertex3fv(vdm->vertexCos ? vface->vvert0->cos : vface->vvert0->co); - glVertex3fv(vdm->vertexCos ? vface->vvert1->cos : vface->vvert1->co); - glVertex3fv(vdm->vertexCos ? vface->vvert2->cos : vface->vvert2->co); - if(vface->vvert3) - glVertex3fv(vdm->vertexCos ? vface->vvert3->cos : vface->vvert3->co); - glEnd(); - - vface = vface->next; - } -} - -/**/ -static void vDM_foreachMappedVert( - DerivedMesh *dm, - void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), - void *userData) -{ -} - -/**/ -static void vDM_foreachMappedEdge( - DerivedMesh *dm, - void (*func)(void *userData, int index, float *v0co, float *v1co), - void *userData) -{ -} - -/**/ -static void vDM_foreachMappedFaceCenter( - DerivedMesh *dm, - void (*func)(void *userData, int index, float *cent, float *no), - void *userData) -{ -} - -/**/ -static void vDM_drawMappedFacesTex( - DerivedMesh *dm, - int (*setDrawParams)(void *userData, int index), - void *userData) -{ - /* not supported yet */ - vDM_drawFacesTex(dm, NULL); -} - -/**/ -static void vDM_drawMappedFaces( - DerivedMesh *dm, - int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), - void *userData, - int useColors) -{ -} - -/**/ -static void vDM_drawMappedEdges( - DerivedMesh *dm, - int (*setDrawOptions)(void *userData, int index), - void *userData) -{ -} - -/**/ -static void vDM_drawMappedEdgesInterp( - DerivedMesh *dm, - int (*setDrawOptions)(void *userData, int index), - void (*setDrawInterpOptions)(void *userData, int index, float t), - void *userData) -{ -} - -/* free all DerivedMesh data */ -static void vDM_release(DerivedMesh *dm) -{ - VDerivedMesh *vdm = (VDerivedMesh*)dm; - - if (DM_release(dm)) { - if(vdm->vertexCos) MEM_freeN(vdm->vertexCos); - MEM_freeN(vdm); - } -} - -/* create derived mesh from verse mesh ... it is used in object mode, when some other client can - * change shared data and want to see this changes in real time too */ -DerivedMesh *derivedmesh_from_versemesh(VNode *vnode, float (*vertexCos)[3]) -{ - VDerivedMesh *vdm = MEM_callocN(sizeof(*vdm), "vdm"); - - vdm->vnode = vnode; - vdm->vertex_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - vdm->polygon_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - vdm->edges = &((VGeomData*)vnode->data)->edges; - - /* vertex and polygon layer has to exist */ - if(vdm->vertex_layer && vdm->polygon_layer) - DM_init(&vdm->dm, vdm->vertex_layer->dl.da.count, BLI_countlist(vdm->edges), vdm->polygon_layer->dl.da.count); - else - DM_init(&vdm->dm, 0, 0, 0); - - vdm->dm.getMinMax = vDM_getMinMax; - - vdm->dm.getNumVerts = vDM_getNumVerts; - vdm->dm.getNumEdges = vDM_getNumEdges; - vdm->dm.getNumFaces = vDM_getNumFaces; - - vdm->dm.getVert = vDM_getVert; - vdm->dm.getEdge = vDM_getEdge; - vdm->dm.getFace = vDM_getFace; - vdm->dm.copyVertArray = vDM_copyVertArray; - vdm->dm.copyEdgeArray = vDM_copyEdgeArray; - vdm->dm.copyFaceArray = vDM_copyFaceArray; - - vdm->dm.foreachMappedVert = vDM_foreachMappedVert; - vdm->dm.foreachMappedEdge = vDM_foreachMappedEdge; - vdm->dm.foreachMappedFaceCenter = vDM_foreachMappedFaceCenter; - - vdm->dm.getVertCos = vDM_getVertCos; - vdm->dm.getVertCo = vDM_getVertCo; - vdm->dm.getVertNo = vDM_getVertNo; - - vdm->dm.drawVerts = vDM_drawVerts; - - vdm->dm.drawEdges = vDM_drawEdges; - vdm->dm.drawLooseEdges = vDM_drawLooseEdges; - vdm->dm.drawUVEdges = vDM_drawUVEdges; - - vdm->dm.drawFacesSolid = vDM_drawFacesSolid; - vdm->dm.drawFacesTex = vDM_drawFacesTex; - vdm->dm.drawFacesColored = vDM_drawFacesColored; - - vdm->dm.drawMappedFacesTex = vDM_drawMappedFacesTex; - vdm->dm.drawMappedFaces = vDM_drawMappedFaces; - vdm->dm.drawMappedEdges = vDM_drawMappedEdges; - vdm->dm.drawMappedEdgesInterp = vDM_drawMappedEdgesInterp; - - vdm->dm.release = vDM_release; - - vdm->vertexCos = vertexCos; - - return (DerivedMesh*) vdm; -} - -#endif - /***/ -DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md) +DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, ModifierData *md) { Mesh *me = ob->data; ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *dm; + md->scene= scene; + if (!(md->mode&eModifierMode_Realtime)) return NULL; if (mti->isDisabled && mti->isDisabled(md)) return NULL; @@ -1973,13 +1403,8 @@ DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md) int numVerts; float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts); - mti->deformVerts(md, ob, NULL, deformedVerts, numVerts); -#ifdef WITH_VERSE - if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts); - else dm = getMeshDerivedMesh(me, ob, deformedVerts); -#else + mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0); dm = getMeshDerivedMesh(me, ob, deformedVerts); -#endif MEM_freeN(deformedVerts); } else { @@ -1992,53 +1417,6 @@ DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md) return dm; } -CustomDataMask get_viewedit_datamask() -{ - CustomDataMask mask = CD_MASK_BAREMESH; - ScrArea *sa; - - /* check if we need tfaces & mcols due to face select or texture paint */ - if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - - if (G.curscreen==NULL) { - /* No screen, happens when saving a blendfile in background mode, - * then loading in the game engine - * just assume we need the mesh info */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - - if((G.fileflags & G_FILE_GAME_MAT) && - (G.fileflags & G_FILE_GAME_MAT_GLSL)) { - mask |= CD_MASK_ORCO; - } - } else { - /* check if we need tfaces & mcols due to view mode */ - for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { - if(sa->spacetype == SPACE_VIEW3D) { - View3D *view = sa->spacedata.first; - if(view->drawtype == OB_SHADED) { - /* this includes normals for mesh_create_shadedColors */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; - } - if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - - if((G.fileflags & G_FILE_GAME_MAT) && - (G.fileflags & G_FILE_GAME_MAT_GLSL)) { - mask |= CD_MASK_ORCO; - } - } - } - } - } - - /* check if we need mcols due to vertex paint or weightpaint */ - if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT) - mask |= CD_MASK_MCOL; - - return mask; -} - static float *get_editmesh_orco_verts(EditMesh *em) { EditVert *eve; @@ -2060,6 +1438,8 @@ static float *get_editmesh_orco_verts(EditMesh *em) return orco; } +/* orco custom data layer */ + static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em) { DerivedMesh *dm; @@ -2111,7 +1491,102 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh * DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); } -static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], +/* weight paint colors */ + +/* Something of a hack, at the moment deal with weightpaint + * by tucking into colors during modifier eval, only in + * wpaint mode. Works ok but need to make sure recalc + * happens on enter/exit wpaint. + */ + +void weight_to_rgb(float input, float *fr, float *fg, float *fb) +{ + float blend; + + blend= ((input/2.0f)+0.5f); + + if (input<=0.25f){ // blue->cyan + *fr= 0.0f; + *fg= blend*input*4.0f; + *fb= blend; + } + else if (input<=0.50f){ // cyan->green + *fr= 0.0f; + *fg= blend; + *fb= blend*(1.0f-((input-0.25f)*4.0f)); + } + else if (input<=0.75){ // green->yellow + *fr= blend * ((input-0.50f)*4.0f); + *fg= blend; + *fb= 0.0f; + } + else if (input<=1.0){ // yellow->red + *fr= blend; + *fg= blend * (1.0f-((input-0.75f)*4.0f)); + *fb= 0.0f; + } +} + +static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col) +{ + Mesh *me = ob->data; + float colf[4], input = 0.0f; + int i; + + if (me->dvert) { + for (i=0; i<me->dvert[vert].totweight; i++) + if (me->dvert[vert].dw[i].def_nr==ob->actdef-1) + input+=me->dvert[vert].dw[i].weight; + } + + CLAMP(input, 0.0f, 1.0f); + + if(coba) + do_colorband(coba, input, colf); + else + weight_to_rgb(input, colf, colf+1, colf+2); + + 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; +} + +static ColorBand *stored_cb= NULL; + +void vDM_ColorBand_store(ColorBand *coba) +{ + stored_cb= coba; +} + +static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm) +{ + Mesh *me = ob->data; + MFace *mf = me->mface; + ColorBand *coba= stored_cb; /* warning, not a local var */ + unsigned char *wtcol; + int i; + + wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap"); + + memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4); + for (i=0; i<me->totface; i++, mf++) { + calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); + calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); + calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); + if (mf->v4) + calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); + } + + CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData); +} + +/* new value for useDeform -1 (hack for the gameengine): + * - apply only the modifier stack of the object, skipping the virtual modifiers, + * - don't apply the key + * - apply deform modifiers and input vertexco + */ +static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, int needMapping, CustomDataMask dataMask, int index) @@ -2125,7 +1600,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], int numVerts = me->totvert; int required_mode; - md = firstmd = modifiers_getVirtualModifierList(ob); + md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob); modifiers_clearErrors(ob); @@ -2142,21 +1617,26 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], else required_mode = eModifierMode_Realtime; if(useDeform) { - if(do_ob_key(ob)) /* shape key makes deform verts */ + if(useDeform > 0 && do_ob_key(scene, ob)) /* shape key makes deform verts */ deformedVerts = mesh_getVertexCos(me, &numVerts); + else if(inputVertexCos) + deformedVerts = inputVertexCos; /* Apply all leading deforming modifiers */ for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if((md->mode & required_mode) != required_mode) continue; if(mti->isDisabled && mti->isDisabled(md)) continue; + if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; if(mti->type == eModifierTypeType_OnlyDeform) { if(!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts); - mti->deformVerts(md, ob, NULL, deformedVerts, numVerts); + mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, useRenderParams, useDeform); } else { break; } @@ -2171,22 +1651,12 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], * coordinates (vpaint, etc.) */ if (deform_r) { -#ifdef WITH_VERSE - if(me->vnode) *deform_r = derivedmesh_from_versemesh(me->vnode, deformedVerts); - else { - *deform_r = CDDM_from_mesh(me, ob); - if(deformedVerts) { - CDDM_apply_vert_coords(*deform_r, deformedVerts); - CDDM_calc_normals(*deform_r); - } - } -#else *deform_r = CDDM_from_mesh(me, ob); + if(deformedVerts) { CDDM_apply_vert_coords(*deform_r, deformedVerts); CDDM_calc_normals(*deform_r); } -#endif } } else { /* default behaviour for meshes */ @@ -2203,16 +1673,11 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], dm = NULL; orcodm = NULL; -#ifdef WITH_VERSE - /* hack to make sure modifiers don't try to use mesh data from a verse - * node - */ - if(me->vnode) dm = derivedmesh_from_versemesh(me->vnode, deformedVerts); -#endif - for(;md; md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if((md->mode & required_mode) != required_mode) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { @@ -2221,6 +1686,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } if(mti->isDisabled && mti->isDisabled(md)) continue; if(needMapping && !modifier_supportsMapping(md)) continue; + if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue; /* add an orco layer if needed by this modifier */ if(dm && mti->requiredDataMask) { @@ -2252,7 +1718,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], } } - mti->deformVerts(md, ob, dm, deformedVerts, numVerts); + mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform); } else { DerivedMesh *ndm; @@ -2273,10 +1739,13 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], CDDM_apply_vert_coords(dm, deformedVerts); CDDM_calc_normals(dm); } + + if(dataMask & CD_MASK_WEIGHT_MCOL) + add_weight_mcol_dm(ob, dm); } /* create an orco derivedmesh in parallel */ - mask= (CustomDataMask)curr->link; + mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); if(mask & CD_MASK_ORCO) { if(!orcodm) orcodm= create_orco_dm(ob, me, NULL); @@ -2296,7 +1765,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DM_set_only_copy(dm, mask); /* add an origspace layer if needed */ - if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE) + if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); @@ -2336,26 +1805,21 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], CDDM_apply_vert_coords(finaldm, deformedVerts); CDDM_calc_normals(finaldm); + + if(dataMask & CD_MASK_WEIGHT_MCOL) + add_weight_mcol_dm(ob, finaldm); } else if(dm) { finaldm = dm; } else { -#ifdef WITH_VERSE - if(me->vnode) - finaldm = derivedmesh_from_versemesh(me->vnode, deformedVerts); - else { - finaldm = CDDM_from_mesh(me, ob); - if(deformedVerts) { - CDDM_apply_vert_coords(finaldm, deformedVerts); - CDDM_calc_normals(finaldm); - } - } -#else finaldm = CDDM_from_mesh(me, ob); + if(deformedVerts) { CDDM_apply_vert_coords(finaldm, deformedVerts); CDDM_calc_normals(finaldm); } -#endif + + if(dataMask & CD_MASK_WEIGHT_MCOL) + add_weight_mcol_dm(ob, finaldm); } /* add an orco layer if needed */ @@ -2408,12 +1872,10 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm) return 1; } -static void editmesh_calc_modifiers(DerivedMesh **cage_r, +static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, DerivedMesh **cage_r, DerivedMesh **final_r, CustomDataMask dataMask) { - Object *ob = G.obedit; - EditMesh *em = G.editMesh; ModifierData *md; float (*deformedVerts)[3] = NULL; CustomDataMask mask; @@ -2429,7 +1891,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, dm = NULL; md = ob->modifiers.first; - + /* we always want to keep original indices */ dataMask |= CD_MASK_ORIGINDEX; @@ -2439,6 +1901,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, for(i = 0; md; i++, md = md->next, curr = curr->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if(!editmesh_modifier_is_enabled(md, dm)) continue; @@ -2500,7 +1964,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, } /* create an orco derivedmesh in parallel */ - mask= (CustomDataMask)curr->link; + mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); if(mask & CD_MASK_ORCO) { if(!orcodm) orcodm= create_orco_dm(ob, ob->data, em); @@ -2517,9 +1981,9 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, } /* set the DerivedMesh to only copy needed data */ - DM_set_only_copy(dm, (CustomDataMask)curr->link); + DM_set_only_copy(dm, (CustomDataMask)GET_INT_FROM_POINTER(curr->link)); - if(((CustomDataMask)curr->link) & CD_MASK_ORIGSPACE) + if(((CustomDataMask)GET_INT_FROM_POINTER(curr->link)) & CD_MASK_ORIGSPACE) if(!CustomData_has_layer(&dm->faceData, CD_ORIGSPACE)) DM_add_face_layer(dm, CD_ORIGSPACE, CD_DEFAULT, NULL); @@ -2585,96 +2049,6 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, MEM_freeN(deformedVerts); } -/***/ - - - /* Something of a hack, at the moment deal with weightpaint - * by tucking into colors during modifier eval, only in - * wpaint mode. Works ok but need to make sure recalc - * happens on enter/exit wpaint. - */ - -void weight_to_rgb(float input, float *fr, float *fg, float *fb) -{ - float blend; - - blend= ((input/2.0f)+0.5f); - - if (input<=0.25f){ // blue->cyan - *fr= 0.0f; - *fg= blend*input*4.0f; - *fb= blend; - } - else if (input<=0.50f){ // cyan->green - *fr= 0.0f; - *fg= blend; - *fb= blend*(1.0f-((input-0.25f)*4.0f)); - } - else if (input<=0.75){ // green->yellow - *fr= blend * ((input-0.50f)*4.0f); - *fg= blend; - *fb= 0.0f; - } - else if (input<=1.0){ // yellow->red - *fr= blend; - *fg= blend * (1.0f-((input-0.75f)*4.0f)); - *fb= 0.0f; - } -} -static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col) -{ - Mesh *me = ob->data; - float colf[4], input = 0.0f; - int i; - - if (me->dvert) { - for (i=0; i<me->dvert[vert].totweight; i++) - if (me->dvert[vert].dw[i].def_nr==ob->actdef-1) - input+=me->dvert[vert].dw[i].weight; - } - - CLAMP(input, 0.0f, 1.0f); - - if(coba) - do_colorband(coba, input, colf); - else - weight_to_rgb(input, colf, colf+1, colf+2); - - 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; -} - -static ColorBand *stored_cb= NULL; - -void vDM_ColorBand_store(ColorBand *coba) -{ - stored_cb= coba; -} - -static unsigned char *calc_weightpaint_colors(Object *ob) -{ - Mesh *me = ob->data; - MFace *mf = me->mface; - ColorBand *coba= stored_cb; /* warning, not a local var */ - unsigned char *wtcol; - int i; - - wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap"); - - memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4); - for (i=0; i<me->totface; i++, mf++) { - calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); - calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); - calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); - if (mf->v4) - calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); - } - - return wtcol; -} - static void clear_mesh_caches(Object *ob) { Mesh *me= ob->data; @@ -2703,64 +2077,38 @@ static void clear_mesh_caches(Object *ob) } } -static void mesh_build_data(Object *ob, CustomDataMask dataMask) +static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask) { - Mesh *me = ob->data; + Object *obact = scene->basact?scene->basact->object:NULL; + int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT); + int needMapping = editing && (ob==obact); float min[3], max[3]; - + clear_mesh_caches(ob); - if(ob!=G.obedit) { - Object *obact = G.scene->basact?G.scene->basact->object:NULL; - int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT); - int needMapping = editing && (ob==obact); - - if( (G.f & G_WEIGHTPAINT) && ob==obact ) { - MCol *wpcol = (MCol*)calc_weightpaint_colors(ob); - int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL); - int prevactive = CustomData_get_active_layer(&me->fdata, CD_MCOL); - int prevrender = CustomData_get_render_layer(&me->fdata, CD_MCOL); - - /* ugly hack here, we temporarily add a new active mcol layer with - weightpaint colors in it, that is then duplicated in CDDM_from_mesh */ - CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, wpcol, me->totface); - CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum); - CustomData_set_layer_render(&me->fdata, CD_MCOL, layernum); - - mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, - &ob->derivedFinal, 0, 1, - needMapping, dataMask, -1); - - CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface); - CustomData_set_layer_active(&me->fdata, CD_MCOL, prevactive); - CustomData_set_layer_render(&me->fdata, CD_MCOL, prevrender); - } else { - mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, - &ob->derivedFinal, G.rendering, 1, - needMapping, dataMask, -1); - } + mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, + &ob->derivedFinal, 0, 1, + needMapping, dataMask, -1); - INIT_MINMAX(min, max); + INIT_MINMAX(min, max); - ob->derivedFinal->getMinMax(ob->derivedFinal, min, max); + ob->derivedFinal->getMinMax(ob->derivedFinal, min, max); - if(!ob->bb) - ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); - boundbox_set_from_min_max(ob->bb, min, max); + if(!ob->bb) + ob->bb= MEM_callocN(sizeof(BoundBox), "bb"); + boundbox_set_from_min_max(ob->bb, min, max); + + ob->derivedFinal->needsFree = 0; + ob->derivedDeform->needsFree = 0; + ob->lastDataMask = dataMask; - ob->derivedFinal->needsFree = 0; - ob->derivedDeform->needsFree = 0; - ob->lastDataMask = dataMask; - } } -static void editmesh_build_data(CustomDataMask dataMask) +static void editmesh_build_data(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask) { float min[3], max[3]; - EditMesh *em = G.editMesh; - - clear_mesh_caches(G.obedit); + clear_mesh_caches(obedit); if (em->derivedFinal) { if (em->derivedFinal!=em->derivedCage) { @@ -2775,225 +2123,143 @@ static void editmesh_build_data(CustomDataMask dataMask) em->derivedCage = NULL; } - editmesh_calc_modifiers(&em->derivedCage, &em->derivedFinal, dataMask); + editmesh_calc_modifiers(scene, obedit, em, &em->derivedCage, &em->derivedFinal, dataMask); em->lastDataMask = dataMask; INIT_MINMAX(min, max); em->derivedFinal->getMinMax(em->derivedFinal, min, max); - if(!G.obedit->bb) - G.obedit->bb= MEM_callocN(sizeof(BoundBox), "bb"); - boundbox_set_from_min_max(G.obedit->bb, min, max); + if(!obedit->bb) + obedit->bb= MEM_callocN(sizeof(BoundBox), "bb"); + boundbox_set_from_min_max(obedit->bb, min, max); em->derivedFinal->needsFree = 0; em->derivedCage->needsFree = 0; } -void makeDerivedMesh(Object *ob, CustomDataMask dataMask) +void makeDerivedMesh(Scene *scene, Object *ob, EditMesh *em, CustomDataMask dataMask) { - if (ob==G.obedit) { - editmesh_build_data(dataMask); + if (em) { + editmesh_build_data(scene, ob, em, dataMask); } else { - mesh_build_data(ob, dataMask); + mesh_build_data(scene, ob, dataMask); } } /***/ -DerivedMesh *mesh_get_derived_final(Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ if(!ob->derivedFinal || (dataMask & ob->lastDataMask) != dataMask) - mesh_build_data(ob, dataMask); + mesh_build_data(scene, ob, dataMask); return ob->derivedFinal; } -DerivedMesh *mesh_get_derived_deform(Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ if(!ob->derivedDeform || (dataMask & ob->lastDataMask) != dataMask) - mesh_build_data(ob, dataMask); + mesh_build_data(scene, ob, dataMask); return ob->derivedDeform; } -/* Move to multires Pin level, returns a copy of the original vertex coords. */ -float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl) +DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask) { - float *vert_copy= NULL; - - if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) { - MultiresLevel *lvl= NULL; - int i; - - /* Make sure all mesh edits are properly stored in the multires data*/ - multires_update_levels(me, 1); - - /* Copy the highest level of multires verts */ - *orig_lvl= me->mr->current; - lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels)); - vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy"); - for(i=0; i<lvl->totvert; ++i) - VecCopyf(&vert_copy[i*3], me->mr->verts[i].co); - - /* Goto the pin level for multires */ - me->mr->newlvl= me->mr->pinlvl; - multires_set_level(ob, me, 1); - } + DerivedMesh *final; - return vert_copy; -} - -/* Propagate the changes to render level - fails if mesh topology changed */ -void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, - const int orig_lvl, CustomDataMask dataMask) -{ - if(me->mr && !(me->mr->flag & MULTIRES_NO_RENDER)) { - if((*dm)->getNumVerts(*dm) == me->totvert && - (*dm)->getNumFaces(*dm) == me->totface) { - MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels)); - DerivedMesh *old= NULL; - MVert *vertdup= NULL; - int i; - - /* Copy the verts into the mesh */ - vertdup= (*dm)->dupVertArray(*dm); - (*dm)->release(*dm); - for(i=0; i<me->totvert; ++i) - me->mvert[i]= vertdup[i]; - /* Free vertdup after use*/ - MEM_freeN(vertdup); - /* Go to the render level */ - me->mr->newlvl= me->mr->renderlvl; - multires_set_level(ob, me, 1); - (*dm)= getMeshDerivedMesh(me, ob, NULL); - - /* Some of the data in dm is referenced externally, so make a copy */ - old= *dm; - (*dm)= CDDM_copy(old); - old->release(old); - - if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, NULL, *dm, NULL); - - /* Restore the original verts */ - me->mr->newlvl= BLI_countlist(&me->mr->levels); - multires_set_level(ob, me, 1); - for(i=0; i<lvl->totvert; ++i) - VecCopyf(me->mvert[i].co, &vert_copy[i*3]); - } - - if(vert_copy) - MEM_freeN(vert_copy); - - me->mr->newlvl= orig_lvl; - multires_set_level(ob, me, 1); - } + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1); + + return final; } -/* Multires note - if mesh has multires enabled, mesh is first set to the Pin level, - where all modifiers are applied, then if the topology hasn't changed, the changes - from modifiers are propagated up to the Render level. */ -DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - vert_copy= multires_render_pin(ob, me, &orig_lvl); - mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask, -1); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 1, 1, 0, dataMask, index); return final; } -DerivedMesh *mesh_create_derived_index_render(Object *ob, CustomDataMask dataMask, int index) +DerivedMesh *mesh_create_derived_view(Scene *scene, Object *ob, CustomDataMask dataMask) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - - vert_copy= multires_render_pin(ob, me, &orig_lvl); - mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask, index); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); + + mesh_calc_modifiers(scene, ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1); return final; } -DerivedMesh *mesh_create_derived_view(Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*vertCos)[3], + CustomDataMask dataMask) { DerivedMesh *final; - - mesh_calc_modifiers(ob, NULL, NULL, &final, 0, 1, 0, dataMask, -1); + + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1); return final; } -DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3], - CustomDataMask dataMask) +DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*vertCos)[3], + CustomDataMask dataMask) { DerivedMesh *final; - mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask, -1); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1); return final; } -DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, +DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob, float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; - Mesh *me= get_mesh(ob); - float *vert_copy= NULL; - int orig_lvl= 0; - vert_copy= multires_render_pin(ob, me, &orig_lvl); - mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1); - multires_render_final(ob, me, &final, vert_copy, orig_lvl, dataMask); + mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 1, 0, 0, dataMask, -1); return final; } /***/ -DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r, +DerivedMesh *editmesh_get_derived_cage_and_final(Scene *scene, Object *obedit, EditMesh *em, DerivedMesh **final_r, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ - if(!G.editMesh->derivedCage || - (G.editMesh->lastDataMask & dataMask) != dataMask) - editmesh_build_data(dataMask); + if(!em->derivedCage || + (em->lastDataMask & dataMask) != dataMask) + editmesh_build_data(scene, obedit, em, dataMask); - *final_r = G.editMesh->derivedFinal; - return G.editMesh->derivedCage; + *final_r = em->derivedFinal; + return em->derivedCage; } -DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask) +DerivedMesh *editmesh_get_derived_cage(Scene *scene, Object *obedit, EditMesh *em, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ - if(!G.editMesh->derivedCage || - (G.editMesh->lastDataMask & dataMask) != dataMask) - editmesh_build_data(dataMask); + if(!em->derivedCage || + (em->lastDataMask & dataMask) != dataMask) + editmesh_build_data(scene, obedit, em, dataMask); - return G.editMesh->derivedCage; + return em->derivedCage; } -DerivedMesh *editmesh_get_derived_base(void) +DerivedMesh *editmesh_get_derived_base(Object *obedit, EditMesh *em) { - return getEditMeshDerivedMesh(G.editMesh, G.obedit, NULL); + return getEditMeshDerivedMesh(em, obedit, NULL); } @@ -3023,7 +2289,7 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, flo /* it stores the normals as floats, but they can still be scaled as shorts (32767 = unit) */ /* in use now by vertex/weight paint and particle generating */ -float *mesh_get_mapped_verts_nors(Object *ob) +float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) { Mesh *me= ob->data; DerivedMesh *dm; @@ -3033,7 +2299,7 @@ float *mesh_get_mapped_verts_nors(Object *ob) if(ob->type!=OB_MESH || me->totvert==0) return NULL; - dm= mesh_get_derived_final(ob, CD_MASK_BAREMESH); + dm= mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map"); if(dm->foreachMappedVert) { @@ -3055,10 +2321,8 @@ float *mesh_get_mapped_verts_nors(Object *ob) /* ********* crazyspace *************** */ -int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**deformcos)[3]) +int editmesh_get_first_deform_matrices(Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]) { - Object *ob = G.obedit; - EditMesh *em = G.editMesh; ModifierData *md; DerivedMesh *dm; int i, a, numleft = 0, numVerts = 0; diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 226e416dad7..a6a5066b574 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -43,6 +43,7 @@ CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include # Reference to the types in makesdna and imbuf CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf # This mod uses the BLI and BLO module CPPFLAGS += -I../../blenlib @@ -53,13 +54,11 @@ CPPFLAGS += -I../../avi CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include # we still refer to /include a bit... -CPPFLAGS += -I../../include +CPPFLAGS += -I../../editors/include # to include the render stuff: CPPFLAGS += -I../../render/extern/include -# for image stamping -CPPFLAGS += -I$(NAN_BMFONT)/include # for sound #CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += $(NAN_SDLCFLAGS) @@ -68,6 +67,7 @@ CPPFLAGS += -I$(NAN_IKSOLVER)/include CPPFLAGS += -I$(NAN_DECIMATION)/include CPPFLAGS += -I$(NAN_ELBEEM)/include CPPFLAGS += -I$(NAN_OPENNL)/include +CPPFLAGS += -I$(NAN_BSP)/include # path to zlib CPPFLAGS += -I$(NAN_ZLIB)/include @@ -82,18 +82,9 @@ CPPFLAGS += -I../../gpu CPPFLAGS += -I.. # path to bullet2, for cloth -CPPFLAGS += -I../../../../extern/bullet2/src - -ifeq ($(WITH_FREETYPE2), true) - CPPFLAGS += -DWITH_FREETYPE2 - CPPFLAGS += -I$(NAN_FREETYPE)/include - CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2 -endif - -ifeq ($(WITH_VERSE), true) - CPPFLAGS += -DWITH_VERSE - CPPFLAGS += -I$(NAN_VERSE)/include -endif +CPPFLAGS += -I$(NAN_BULLET2)/include +CPPFLAGS += -I$(NAN_FREETYPE)/include +CPPFLAGS += -I$(NAN_FREETYPE)/include/freetype2 ifeq ($(WITH_FFMPEG),true) CPPFLAGS += -DWITH_FFMPEG diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e0afdec5e23..d54bc749b71 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -35,16 +35,17 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" -#include "DNA_ipo_types.h" #include "DNA_key_types.h" #include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_anim.h" #include "BKE_armature.h" @@ -52,7 +53,7 @@ #include "BKE_constraint.h" #include "BKE_displist.h" #include "BKE_global.h" -#include "BKE_ipo.h" +#include "BKE_fcurve.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -64,7 +65,10 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" -#include "nla.h" +#include "RNA_access.h" +#include "RNA_types.h" + +//XXX #include "nla.h" /* *********************** NOTE ON POSE AND ACTION ********************** @@ -81,52 +85,34 @@ /* ***************** Library data level operations on action ************** */ -static void make_local_action_channels(bAction *act) +bAction *add_empty_action(const char name[]) { - bActionChannel *chan; - bConstraintChannel *conchan; - - for (chan=act->chanbase.first; chan; chan=chan->next) { - if(chan->ipo) { - if(chan->ipo->id.us==1) { - chan->ipo->id.lib= NULL; - chan->ipo->id.flag= LIB_LOCAL; - new_id(0, (ID *)chan->ipo, 0); - } - else { - chan->ipo= copy_ipo(chan->ipo); - } - } - for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) { - if(conchan->ipo) { - if(conchan->ipo->id.us==1) { - conchan->ipo->id.lib= NULL; - conchan->ipo->id.flag= LIB_LOCAL; - new_id(0, (ID *)conchan->ipo, 0); - } - else { - conchan->ipo= copy_ipo(conchan->ipo); - } - } - } - } -} + bAction *act; + + act= alloc_libblock(&G.main->action, ID_AC, name); + act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore + act->id.us++; + + return act; +} +// does copy_fcurve... void make_local_action(bAction *act) { - Object *ob; + // Object *ob; bAction *actn; int local=0, lib=0; - if(act->id.lib==0) return; - if(act->id.us==1) { + if (act->id.lib==0) return; + if (act->id.us==1) { act->id.lib= 0; act->id.flag= LIB_LOCAL; - make_local_action_channels(act); + //make_local_action_channels(act); new_id(0, (ID *)act, 0); return; } +#if 0 // XXX old animation system ob= G.main->object.first; while(ob) { if(ob->action==act) { @@ -135,17 +121,19 @@ void make_local_action(bAction *act) } ob= ob->id.next; } +#endif if(local && lib==0) { act->id.lib= 0; act->id.flag= LIB_LOCAL; - make_local_action_channels(act); + //make_local_action_channels(act); new_id(0, (ID *)act, 0); } else if(local && lib) { actn= copy_action(act); actn->id.us= 0; +#if 0 // XXX old animation system ob= G.main->object.first; while(ob) { if(ob->action==act) { @@ -158,24 +146,20 @@ void make_local_action(bAction *act) } ob= ob->id.next; } +#endif // XXX old animation system } } void free_action (bAction *act) { - bActionChannel *chan; + /* sanity check */ + if (act == NULL) + return; - /* Free channels */ - for (chan=act->chanbase.first; chan; chan=chan->next) { - if (chan->ipo) - chan->ipo->id.us--; - free_constraint_channels(&chan->constraintChannels); - } + /* Free F-Curves */ + free_fcurves(&act->curves); - if (act->chanbase.first) - BLI_freelistN(&act->chanbase); - /* Free groups */ if (act->groups.first) BLI_freelistN(&act->groups); @@ -188,42 +172,237 @@ void free_action (bAction *act) bAction *copy_action (bAction *src) { bAction *dst = NULL; - bActionChannel *dchan, *schan; bActionGroup *dgrp, *sgrp; + FCurve *dfcu, *sfcu; - if (!src) return NULL; - + if (src == NULL) + return NULL; dst= copy_libblock(src); - duplicatelist(&(dst->chanbase), &(src->chanbase)); - duplicatelist(&(dst->groups), &(src->groups)); - duplicatelist(&(dst->markers), &(src->markers)); + /* duplicate the lists of groups and markers */ + BLI_duplicatelist(&dst->groups, &src->groups); + BLI_duplicatelist(&dst->markers, &src->markers); + + /* copy F-Curves, fixing up the links as we go */ + dst->curves.first= dst->curves.last= NULL; - for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) { + for (sfcu= src->curves.first; sfcu; sfcu= sfcu->next) { + /* duplicate F-Curve */ + dfcu= copy_fcurve(sfcu); + BLI_addtail(&dst->curves, dfcu); + + /* fix group links (kindof bad list-in-list search, but this is the most reliable way) */ for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) { - if (dchan->grp == sgrp) { - dchan->grp= dgrp; + if (sfcu->grp == sgrp) { + dfcu->grp= dgrp; - if (dgrp->channels.first == schan) - dgrp->channels.first= dchan; - if (dgrp->channels.last == schan) - dgrp->channels.last= dchan; + if (dgrp->channels.first == sfcu) + dgrp->channels.first= dfcu; + if (dgrp->channels.last == sfcu) + dgrp->channels.last= dfcu; break; } } - - dchan->ipo = copy_ipo(dchan->ipo); - copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); } - dst->id.flag |= LIB_FAKEUSER; + dst->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore dst->id.us++; return dst; } +/* Get the active action-group for an Action */ +bActionGroup *get_active_actiongroup (bAction *act) +{ + bActionGroup *agrp= NULL; + + if (act && act->groups.first) { + for (agrp= act->groups.first; agrp; agrp= agrp->next) { + if (agrp->flag & AGRP_ACTIVE) + break; + } + } + + return agrp; +} + +/* Make the given Action-Group the active one */ +void set_active_action_group (bAction *act, bActionGroup *agrp, short select) +{ + bActionGroup *grp; + + /* sanity checks */ + if (act == NULL) + return; + + /* Deactive all others */ + for (grp= act->groups.first; grp; grp= grp->next) { + if ((grp==agrp) && (select)) + grp->flag |= AGRP_ACTIVE; + else + grp->flag &= ~AGRP_ACTIVE; + } +} + +/* Add given channel into (active) group + * - assumes that channel is not linked to anything anymore + * - always adds at the end of the group + */ +void action_groups_add_channel (bAction *act, bActionGroup *agrp, FCurve *fcurve) +{ + FCurve *fcu; + short done=0; + + /* sanity checks */ + if (ELEM3(NULL, act, agrp, fcurve)) + return; + + /* if no channels, just add to two lists at the same time */ + if (act->curves.first == NULL) { + fcurve->next = fcurve->prev = NULL; + + agrp->channels.first = agrp->channels.last = fcurve; + act->curves.first = act->curves.last = fcurve; + + fcurve->grp= agrp; + return; + } + + /* try to find a channel to slot this in before/after */ + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + /* if channel has no group, then we have ungrouped channels, which should always occur after groups */ + if (fcu->grp == NULL) { + BLI_insertlinkbefore(&act->curves, fcu, fcurve); + + if (agrp->channels.first == NULL) + agrp->channels.first= fcurve; + agrp->channels.last= fcurve; + + done= 1; + break; + } + + /* if channel has group after current, we can now insert (otherwise we have gone too far) */ + else if (fcu->grp == agrp->next) { + BLI_insertlinkbefore(&act->curves, fcu, fcurve); + + if (agrp->channels.first == NULL) + agrp->channels.first= fcurve; + agrp->channels.last= fcurve; + + done= 1; + break; + } + + /* if channel has group we're targeting, check whether it is the last one of these */ + else if (fcu->grp == agrp) { + if ((fcu->next) && (fcu->next->grp != agrp)) { + BLI_insertlinkafter(&act->curves, fcu, fcurve); + agrp->channels.last= fcurve; + done= 1; + break; + } + else if (fcu->next == NULL) { + BLI_addtail(&act->curves, fcurve); + agrp->channels.last= fcurve; + done= 1; + break; + } + } + + /* if channel has group before target, check whether the next one is something after target */ + else if (fcu->grp == agrp->prev) { + if (fcu->next) { + if ((fcu->next->grp != fcu->grp) && (fcu->next->grp != agrp)) { + BLI_insertlinkafter(&act->curves, fcu, fcurve); + + agrp->channels.first= fcurve; + agrp->channels.last= fcurve; + + done= 1; + break; + } + } + else { + BLI_insertlinkafter(&act->curves, fcu, fcurve); + + agrp->channels.first= fcurve; + agrp->channels.last= fcurve; + + done= 1; + break; + } + } + } + + /* only if added, set channel as belonging to this group */ + if (done) { + //printf("FCurve added to group \n"); + fcurve->grp= agrp; + } + else { + printf("Error: FCurve '%s' couldn't be added to Group '%s' \n", fcurve->rna_path, agrp->name); + BLI_addtail(&act->curves, fcurve); + } +} + +/* Remove the given channel from all groups */ +void action_groups_remove_channel (bAction *act, FCurve *fcu) +{ + /* sanity checks */ + if (ELEM(NULL, act, fcu)) + return; + + /* check if any group used this directly */ + if (fcu->grp) { + bActionGroup *agrp= fcu->grp; + + if (agrp->channels.first == agrp->channels.last) { + if (agrp->channels.first == fcu) { + agrp->channels.first= NULL; + agrp->channels.last= NULL; + } + } + else if (agrp->channels.first == fcu) { + if ((fcu->next) && (fcu->next->grp==agrp)) + agrp->channels.first= fcu->next; + else + agrp->channels.first= NULL; + } + else if (agrp->channels.last == fcu) { + if ((fcu->prev) && (fcu->prev->grp==agrp)) + agrp->channels.last= fcu->prev; + else + agrp->channels.last= NULL; + } + + fcu->grp= NULL; + } + + /* now just remove from list */ + BLI_remlink(&act->curves, fcu); +} + +/* Find a group with the given name */ +bActionGroup *action_groups_find_named (bAction *act, const char name[]) +{ + bActionGroup *grp; + + /* sanity checks */ + if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0)) + return NULL; + + /* do string comparisons */ + for (grp= act->groups.first; grp; grp= grp->next) { + if (strcmp(grp->name, name) == 0) + return grp; + } + + /* not found */ + return NULL; +} /* ************************ Pose channels *************** */ @@ -232,12 +411,13 @@ bPoseChannel *get_pose_channel(const bPose *pose, const char *name) { bPoseChannel *chan; - if(pose==NULL) return NULL; + if (pose==NULL) return NULL; for (chan=pose->chanbase.first; chan; chan=chan->next) { - if(chan->name[0] == name[0]) + if (chan->name[0] == name[0]) { if (!strcmp (chan->name, name)) return chan; + } } return NULL; @@ -249,11 +429,10 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) { bPoseChannel *chan; - if (!pose) { + if (pose == NULL) return NULL; - } - /* See if this channel exists */ + /* See if this channel exists */ for (chan=pose->chanbase.first; chan; chan=chan->next) { if (!strcmp (name, chan->name)) return chan; @@ -262,10 +441,10 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) /* If not, create it and add it */ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); - strncpy (chan->name, name, 31); + strncpy(chan->name, name, 31); /* init vars to prevent math errors */ - chan->quat[0] = 1.0F; - chan->size[0] = chan->size[1] = chan->size[2] = 1.0F; + chan->quat[0] = 1.0f; + chan->size[0] = chan->size[1] = chan->size[2] = 1.0f; chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f; @@ -273,14 +452,32 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) Mat4One(chan->constinv); - BLI_addtail (&pose->chanbase, chan); + BLI_addtail(&pose->chanbase, chan); return chan; } +/* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */ +bPoseChannel *get_active_posechannel (Object *ob) +{ + bArmature *arm= (ob) ? ob->data : NULL; + bPoseChannel *pchan; + + if ELEM3(NULL, ob, ob->pose, arm) + return NULL; + + /* find active */ + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if ((pchan->bone) && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) + return pchan; + } + + return NULL; +} + /* dst should be freed already, makes entire duplicate */ -void copy_pose(bPose **dst, bPose *src, int copycon) +void copy_pose (bPose **dst, bPose *src, int copycon) { bPose *outPose; bPoseChannel *pchan; @@ -299,7 +496,7 @@ void copy_pose(bPose **dst, bPose *src, int copycon) outPose= MEM_callocN(sizeof(bPose), "pose"); - duplicatelist(&outPose->chanbase, &src->chanbase); + BLI_duplicatelist(&outPose->chanbase, &src->chanbase); if (copycon) { for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { @@ -363,7 +560,7 @@ void game_copy_pose(bPose **dst, bPose *src) out= MEM_dupallocN(src); out->agroups.first= out->agroups.last= NULL; - duplicatelist(&out->chanbase, &src->chanbase); + BLI_duplicatelist(&out->chanbase, &src->chanbase); /* remap pointers */ ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); @@ -401,7 +598,9 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); + VECCOPY(pchan->eul, chan->eul); QUATCOPY(pchan->quat, chan->quat); + pchan->rotmode= chan->rotmode; Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat); Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat); pchan->flag= chan->flag; @@ -497,53 +696,24 @@ void framechange_poses_clear_unkeyed(void) /* ************************ END Pose channels *************** */ -/* ************************ Action channels *************** */ - - -bActionChannel *get_action_channel(bAction *act, const char *name) -{ - bActionChannel *chan; - - if (!act || !name) - return NULL; - - for (chan = act->chanbase.first; chan; chan=chan->next) { - if (!strcmp (chan->name, name)) - return chan; - } - - return NULL; -} - -/* returns existing channel, or adds new one. In latter case it doesnt activate it, context is required for that */ -bActionChannel *verify_action_channel(bAction *act, const char *name) -{ - bActionChannel *chan; - - chan= get_action_channel(act, name); - if (chan == NULL) { - chan = MEM_callocN (sizeof(bActionChannel), "actionChannel"); - strncpy(chan->name, name, 31); - BLI_addtail(&act->chanbase, chan); - } - return chan; -} - /* ************** time ****************** */ static bActionStrip *get_active_strip(Object *ob) { +#if 0 // XXX old animation system bActionStrip *strip; if(ob->action==NULL) return NULL; - + for (strip=ob->nlastrips.first; strip; strip=strip->next) if(strip->flag & ACTSTRIP_ACTIVE) break; if(strip && strip->act==ob->action) return strip; +#endif // XXX old animation system + return NULL; } @@ -556,7 +726,7 @@ static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat); if (strip->scale == 0.0f) strip->scale= 1.0f; - scale = fabs(strip->scale); /* scale must be positive (for now) */ + scale = (float)fabs(strip->scale); /* scale must be positive (for now) */ actlength = strip->actend-strip->actstart; if (actlength == 0.0f) actlength = 1.0f; @@ -590,6 +760,184 @@ float get_action_frame_inv(Object *ob, float cframe) } + + +/* Calculate the extents of given action */ +void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden) +{ + FCurve *fcu; + float min=999999999.0f, max=-999999999.0f; + short foundvert=0; + + if (act) { + for (fcu= act->curves.first; fcu; fcu= fcu->next) { + if (fcu->totvert) { + float nmin, nmax; + + /* get extents for this curve */ + calc_fcurve_range(fcu, &nmin, &nmax); + + /* compare to the running tally */ + min= MIN2(min, nmin); + max= MAX2(max, nmax); + + foundvert= 1; + } + } + } + + if (foundvert) { + if(min==max) max+= 1.0f; + *start= min; + *end= max; + } + else { + *start= 0.0f; + *end= 1.0f; + } +} + +/* Copy the data from the action-pose (src) into the pose */ +/* both args are assumed to be valid */ +/* exported to game engine */ +void extract_pose_from_pose(bPose *pose, const bPose *src) +{ + const bPoseChannel *schan; + bPoseChannel *pchan= pose->chanbase.first; + + if (pose==src) { + printf("extract_pose_from_pose source and target are the same\n"); + return; + } + + for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) { + copy_pose_channel_data(pchan, schan); + } +} + +/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */ +void rest_pose(bPose *pose) +{ + bPoseChannel *pchan; + int i; + + if (!pose) + return; + + memset(pose->stride_offset, 0, sizeof(pose->stride_offset)); + memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); + + for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){ + for (i=0; i<3; i++) { + pchan->loc[i]= 0.0f; + pchan->quat[i+1]= 0.0f; + pchan->eul[i]= 0.0f; + pchan->size[i]= 1.0f; + } + pchan->quat[0]= 1.0f; + + pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); + } +} + +/* both poses should be in sync */ +void copy_pose_result(bPose *to, bPose *from) +{ + bPoseChannel *pchanto, *pchanfrom; + + if(to==NULL || from==NULL) { + printf("pose result copy error\n"); // debug temp + return; + } + + if (to==from) { + printf("copy_pose_result source and target are the same\n"); + return; + } + + + for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) { + pchanto= get_pose_channel(to, pchanfrom->name); + if(pchanto) { + Mat4CpyMat4(pchanto->pose_mat, pchanfrom->pose_mat); + Mat4CpyMat4(pchanto->chan_mat, pchanfrom->chan_mat); + + /* used for local constraints */ + VECCOPY(pchanto->loc, pchanfrom->loc); + QUATCOPY(pchanto->quat, pchanfrom->quat); + VECCOPY(pchanto->eul, pchanfrom->eul); + VECCOPY(pchanto->size, pchanfrom->size); + + VECCOPY(pchanto->pose_head, pchanfrom->pose_head); + VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail); + pchanto->flag= pchanfrom->flag; + } + } +} + +/* For the calculation of the effects of an Action at the given frame on an object + * This is currently only used for the Action Constraint + */ +void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) +{ + bActionGroup *agrp= action_groups_find_named(act, groupname); + + /* clear workob */ + clear_workob(workob); + + /* init workob */ + Mat4CpyMat4(workob->obmat, ob->obmat); + Mat4CpyMat4(workob->parentinv, ob->parentinv); + Mat4CpyMat4(workob->constinv, ob->constinv); + workob->parent= ob->parent; + workob->track= ob->track; + + workob->trackflag= ob->trackflag; + workob->upflag= ob->upflag; + + workob->partype= ob->partype; + workob->par1= ob->par1; + workob->par2= ob->par2; + workob->par3= ob->par3; + + workob->constraints.first = ob->constraints.first; + workob->constraints.last = ob->constraints.last; + + workob->pose= pose; /* need to set pose too, since this is used for both types of Action Constraint */ + + strcpy(workob->parsubstr, ob->parsubstr); + strcpy(workob->id.name, "OB<ConstrWorkOb>"); /* we don't use real object name, otherwise RNA screws with the real thing */ + + /* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */ + if (agrp) { + /* specifically evaluate this group only */ + PointerRNA id_ptr; + + /* get RNA-pointer for the workob's ID */ + RNA_id_pointer_create(&workob->id, &id_ptr); + + /* execute action for this group only */ + animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe); + } + else { + AnimData adt; + + /* init animdata, and attach to workob */ + memset(&adt, 0, sizeof(AnimData)); + workob->adt= &adt; + + adt.recalc= ADT_RECALC_ANIM; + adt.action= act; + + /* execute effects of Action on to workob (or it's PoseChannels) */ + BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM); + } +} + +/* ********** NLA with non-poses works with ipo channels ********** */ + +#if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) + /* ************************ Blending with NLA *************** */ static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode) @@ -697,7 +1045,6 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode) bPoseChannel *dchan; const bPoseChannel *schan; bConstraint *dcon, *scon; - float dquat[4], squat[4]; float dstweight; int i; @@ -719,23 +1066,34 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode) /* Do the transformation blend */ if (schan->flag & POSE_ROT) { - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if(mode==ACTSTRIPMODE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else { - QuatMulFac(squat, srcweight); - QuatMul(dchan->quat, dquat, squat); + /* quat interpolation done separate */ + if (schan->rotmode == PCHAN_ROT_QUAT) { + float dquat[4], squat[4]; + + QUATCOPY(dquat, dchan->quat); + QUATCOPY(squat, schan->quat); + if (mode==ACTSTRIPMODE_BLEND) + QuatInterpol(dchan->quat, dquat, squat, srcweight); + else { + QuatMulFac(squat, srcweight); + QuatMul(dchan->quat, dquat, squat); + } + + NormalQuat(dchan->quat); } - - NormalQuat (dchan->quat); } - for (i=0; i<3; i++){ + for (i=0; i<3; i++) { + /* blending for loc and scale are pretty self-explanatory... */ if (schan->flag & POSE_LOC) dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); if (schan->flag & POSE_SIZE) dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); + + /* euler-rotation interpolation done here instead... */ + // FIXME: are these results decent? + if ((schan->flag & POSE_ROT) && (schan->rotmode)) + dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); } dchan->flag |= schan->flag; } @@ -749,167 +1107,6 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode) dst->ctime= src->ctime; } - -void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden) -{ - const bActionChannel *chan; - const bConstraintChannel *conchan; - const IpoCurve *icu; - float min=999999999.0f, max=-999999999.0; - int foundvert=0; - - if(act) { - for (chan=act->chanbase.first; chan; chan=chan->next) { - if(incl_hidden || (chan->flag & ACHAN_HIDDEN)==0) { - if(chan->ipo) { - for (icu=chan->ipo->curve.first; icu; icu=icu->next) { - if(icu->totvert) { - min= MIN2 (min, icu->bezt[0].vec[1][0]); - max= MAX2 (max, icu->bezt[icu->totvert-1].vec[1][0]); - foundvert=1; - } - } - } - for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) { - if(conchan->ipo) { - for (icu=conchan->ipo->curve.first; icu; icu=icu->next) { - if(icu->totvert) { - min= MIN2 (min, icu->bezt[0].vec[1][0]); - max= MAX2 (max, icu->bezt[icu->totvert-1].vec[1][0]); - foundvert=1; - } - } - } - } - } - } - } - if (foundvert) { - if(min==max) max+= 1.0f; - *start= min; - *end= max; - } - else { - *start= 0.0f; - *end= 1.0f; - } -} - -/* Copy the data from the action-pose (src) into the pose */ -/* both args are assumed to be valid */ -/* exported to game engine */ -void extract_pose_from_pose(bPose *pose, const bPose *src) -{ - const bPoseChannel *schan; - bPoseChannel *pchan= pose->chanbase.first; - - if (pose==src) { - printf("extract_pose_from_pose source and target are the same\n"); - return; - } - - for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) { - copy_pose_channel_data(pchan, schan); - } -} - -/* Pose should exist, can have any number of channels too (used for constraint) */ -void extract_pose_from_action(bPose *pose, bAction *act, float ctime) -{ - bActionChannel *achan; - bPoseChannel *pchan; - Ipo *ipo; - - if (!act) - return; - if (!pose) - return; - - /* Copy the data from the action into the pose */ - for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) { - /* skip this pose channel if it has been tagged as having unkeyed poses */ - if ((pchan->bone) && (pchan->bone->flag & BONE_UNKEYED)) - continue; - - /* get action channel and clear pchan-transform flags */ - achan= get_action_channel(act, pchan->name); - pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); - - if (achan) { - ipo = achan->ipo; - if (ipo) { - /* Evaluates and sets the internal ipo value */ - calc_ipo(ipo, ctime); - /* This call also sets the pchan flags */ - execute_action_ipo(achan, pchan); - } - /* 0 = do all ipos, not only drivers */ - do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime, 0); - } - } - - pose->ctime= ctime; /* used for cyclic offset matching */ -} - -/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */ -void rest_pose(bPose *pose) -{ - bPoseChannel *pchan; - int i; - - if (!pose) - return; - - memset(pose->stride_offset, 0, sizeof(pose->stride_offset)); - memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); - - for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){ - for (i=0; i<3; i++) { - pchan->loc[i]= 0.0f; - pchan->quat[i+1]= 0.0f; - pchan->size[i]= 1.0f; - } - pchan->quat[0]= 1.0f; - - pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); - } -} - -/* both poses should be in sync */ -void copy_pose_result(bPose *to, bPose *from) -{ - bPoseChannel *pchanto, *pchanfrom; - - if(to==NULL || from==NULL) { - printf("pose result copy error\n"); // debug temp - return; - } - - if (to==from) { - printf("copy_pose_result source and target are the same\n"); - return; - } - - - for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) { - pchanto= get_pose_channel(to, pchanfrom->name); - if(pchanto) { - Mat4CpyMat4(pchanto->pose_mat, pchanfrom->pose_mat); - Mat4CpyMat4(pchanto->chan_mat, pchanfrom->chan_mat); - /* used for local constraints */ - VECCOPY(pchanto->loc, pchanfrom->loc); - QUATCOPY(pchanto->quat, pchanfrom->quat); - VECCOPY(pchanto->size, pchanfrom->size); - - VECCOPY(pchanto->pose_head, pchanfrom->pose_head); - VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail); - pchanto->flag= pchanfrom->flag; - } - } -} - -/* ********** NLA with non-poses works with ipo channels ********** */ - typedef struct NlaIpoChannel { struct NlaIpoChannel *next, *prev; float val; @@ -1028,7 +1225,7 @@ int execute_ipochannels(ListBase *lb) /* this now only used for repeating cycles, to enable fields and blur. */ /* the whole time control in blender needs serious thinking... */ -static float nla_time(float cfra, float unit) +static float nla_time(Scene *scene, float cfra, float unit) { extern float bluroffs; // bad construct, borrowed from object.c for now extern float fieldoffs; @@ -1037,7 +1234,7 @@ static float nla_time(float cfra, float unit) cfra+= unit*(bluroffs+fieldoffs); /* global time */ - cfra*= G.scene->r.framelen; + cfra*= scene->r.framelen; return cfra; } @@ -1191,48 +1388,9 @@ static Object *get_parent_path(Object *ob) /* ************** do the action ************ */ -/* For the calculation of the effects of an action at the given frame on an object - * This is currently only used for the action constraint - */ -void what_does_obaction (Object *ob, bAction *act, float cframe) -{ - ListBase tchanbase= {NULL, NULL}; - - clear_workob(); - Mat4CpyMat4(workob.obmat, ob->obmat); - Mat4CpyMat4(workob.parentinv, ob->parentinv); - Mat4CpyMat4(workob.constinv, ob->constinv); - workob.parent= ob->parent; - workob.track= ob->track; - - workob.trackflag= ob->trackflag; - workob.upflag= ob->upflag; - - workob.partype= ob->partype; - workob.par1= ob->par1; - workob.par2= ob->par2; - workob.par3= ob->par3; - - workob.constraints.first = ob->constraints.first; - workob.constraints.last = ob->constraints.last; - - strcpy(workob.parsubstr, ob->parsubstr); - strcpy(workob.id.name, ob->id.name); - - /* extract_ipochannels_from_action needs id's! */ - workob.action= act; - - extract_ipochannels_from_action(&tchanbase, &workob.id, act, "Object", bsystem_time(&workob, cframe, 0.0)); - - if (tchanbase.first) { - execute_ipochannels(&tchanbase); - BLI_freelistN(&tchanbase); - } -} - /* ----- nla, etc. --------- */ -static void do_nla(Object *ob, int blocktype) +static void do_nla(Scene *scene, Object *ob, int blocktype) { bPose *tpose= NULL; Key *key= NULL; @@ -1240,7 +1398,7 @@ static void do_nla(Object *ob, int blocktype) bActionStrip *strip, *striplast=NULL, *stripfirst=NULL; float striptime, frametime, length, actlength; float blendfac, stripframe; - float scene_cfra= frame_to_float(G.scene->r.cfra); + float scene_cfra= frame_to_float(scene, scene->r.cfra); int doit, dostride; if(blocktype==ID_AR) { @@ -1306,11 +1464,11 @@ static void do_nla(Object *ob, int blocktype) if (cu->flag & CU_PATH){ /* Ensure we have a valid path */ - if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(parent, 0); + if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(scene, parent, 0); if(cu->path) { /* Find the position on the path */ - ctime= bsystem_time(ob, scene_cfra, 0.0); + ctime= bsystem_time(scene, ob, scene_cfra, 0.0); if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { /* correct for actions not starting on zero */ @@ -1332,7 +1490,7 @@ static void do_nla(Object *ob, int blocktype) } frametime = (striptime * actlength) + strip->actstart; - frametime= bsystem_time(ob, frametime, 0.0); + frametime= bsystem_time(scene, ob, frametime, 0.0); if(blocktype==ID_AR) { extract_pose_from_action (tpose, strip->act, frametime); @@ -1362,7 +1520,7 @@ static void do_nla(Object *ob, int blocktype) } frametime = (striptime * actlength) + strip->actstart; - frametime= nla_time(frametime, (float)strip->repeat); + frametime= nla_time(scene, frametime, (float)strip->repeat); if(blocktype==ID_AR) { extract_pose_from_action (tpose, strip->act, frametime); @@ -1383,7 +1541,7 @@ static void do_nla(Object *ob, int blocktype) frametime = actlength * (strip->repeat-(int)strip->repeat); if(frametime<=0.000001f) frametime= actlength; /* rounding errors... */ - frametime= bsystem_time(ob, frametime+strip->actstart, 0.0); + frametime= bsystem_time(scene, ob, frametime+strip->actstart, 0.0); if(blocktype==ID_AR) extract_pose_from_action (tpose, strip->act, frametime); @@ -1448,55 +1606,4 @@ static void do_nla(Object *ob, int blocktype) BLI_freelistN(&chanbase); } -void do_all_pose_actions(Object *ob) -{ - /* only to have safe calls from editor */ - if(ob==NULL) return; - if(ob->type!=OB_ARMATURE || ob->pose==NULL) return; - - if(ob->pose->flag & POSE_LOCKED) { /* no actions to execute while transform */ - if(ob->pose->flag & POSE_DO_UNLOCK) - ob->pose->flag &= ~(POSE_LOCKED|POSE_DO_UNLOCK); - } - else if(ob->action && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || ob->nlastrips.first==NULL) ) { - float cframe= (float) G.scene->r.cfra; - - cframe= get_action_frame(ob, cframe); - - extract_pose_from_action (ob->pose, ob->action, bsystem_time(ob, cframe, 0.0)); - } - else if(ob->nlastrips.first) { - do_nla(ob, ID_AR); - } - - /* clear POSE_DO_UNLOCK flags that might have slipped through (just in case) */ - ob->pose->flag &= ~POSE_DO_UNLOCK; -} - -/* called from where_is_object */ -void do_all_object_actions(Object *ob) -{ - if(ob==NULL) return; - if(ob->dup_group) return; /* prevent conflicts, might add smarter check later */ - - /* Do local action */ - if(ob->action && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || ob->nlastrips.first==NULL) ) { - ListBase tchanbase= {NULL, NULL}; - Key *key= ob_get_key(ob); - float cframe= (float) G.scene->r.cfra; - - cframe= get_action_frame(ob, cframe); - - extract_ipochannels_from_action(&tchanbase, &ob->id, ob->action, "Object", bsystem_time(ob, cframe, 0.0)); - if(key) - extract_ipochannels_from_action(&tchanbase, &key->id, ob->action, "Shape", bsystem_time(ob, cframe, 0.0)); - - if(tchanbase.first) { - execute_ipochannels(&tchanbase); - BLI_freelistN(&tchanbase); - } - } - else if(ob->nlastrips.first) { - do_nla(ob, ID_OB); - } -} +#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 50be417c8ef..1aceca454d2 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_editVert.h" #include "BLI_arithb.h" #include "BLI_rand.h" #include "DNA_listBase.h" @@ -68,13 +69,13 @@ #include "BKE_particle.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" - #ifdef HAVE_CONFIG_H #include <config.h> #endif -static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated); +#include "ED_mesh.h" + +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated); void free_path(Path *path) { @@ -100,8 +101,10 @@ void calc_curvepath(Object *ob) if(ob==NULL || ob->type != OB_CURVE) return; cu= ob->data; - if(ob==G.obedit) nu= editNurb.first; - else nu= cu->nurb.first; + if(cu->editnurb) + nu= cu->editnurb->first; + else + nu= cu->nurb.first; if(cu->path) free_path(cu->path); cu->path= NULL; @@ -301,7 +304,7 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i return dob; } -static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { DupliObject *dob; Group *group; @@ -316,7 +319,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) /* handles animated groups, and */ /* we need to check update for objects that are not in scene... */ - group_handle_recalc_and_update(ob, group); + group_handle_recalc_and_update(scene, ob, group); animated= animated || group_is_animated(ob, group); for(go= group->gobject.first; go; go= go->next) { @@ -337,14 +340,14 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) if(go->ob->transflag & OB_DUPLI) { Mat4CpyMat4(dob->ob->obmat, dob->mat); - object_duplilist_recursive((ID *)group, go->ob, lb, ob->obmat, level+1, animated); + object_duplilist_recursive((ID *)group, scene, go->ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Object *ob, int level, int animated) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int level, int animated) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -354,31 +357,33 @@ static void frames_duplilist(ListBase *lb, Object *ob, int level, int animated) /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - cfrao= G.scene->r.cfra; + cfrao= scene->r.cfra; if(ob->parent==NULL && ob->track==NULL && ob->ipo==NULL && ob->constraints.first==NULL) return; if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0; copyob= *ob; /* store transform info */ - for(G.scene->r.cfra= ob->dupsta; G.scene->r.cfra<=ob->dupend; G.scene->r.cfra++) { + for(scene->r.cfra= ob->dupsta; scene->r.cfra<=ob->dupend; scene->r.cfra++) { ok= 1; if(ob->dupoff) { - ok= G.scene->r.cfra - ob->dupsta; + ok= scene->r.cfra - ob->dupsta; ok= ok % (ob->dupon+ob->dupoff); if(ok < ob->dupon) ok= 1; else ok= 0; } if(ok) { - do_ob_ipo(ob); - where_is_object_time(ob, (float)G.scene->r.cfra); - dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, G.scene->r.cfra, OB_DUPLIFRAMES, animated); +#if 0 // XXX old animation system + do_ob_ipo(scene, ob); +#endif // XXX old animation system + where_is_object_time(scene, ob, (float)scene->r.cfra); + dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated); Mat4CpyMat4(dob->omat, copyob.obmat); } } *ob= copyob; /* restore transform info */ - G.scene->r.cfra= cfrao; + scene->r.cfra= cfrao; enable_cu_speed= 1; } @@ -389,6 +394,7 @@ struct vertexDupliData { ListBase *lb; float pmat[4][4]; float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */ + Scene *scene; Object *ob, *par; float (*orco)[3]; }; @@ -429,36 +435,39 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n float tmpmat[4][4]; Mat4CpyMat4(tmpmat, vdd->ob->obmat); Mat4CpyMat4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->ob, vdd->lb, obmat, vdd->level+1, vdd->animated); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->level+1, vdd->animated); Mat4CpyMat4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level, int animated) +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; - Mesh *me; + Mesh *me= par->data; Base *base = NULL; - float vec[3], no[3], pmat[4][4]; - int lay, totvert, a, oblay; DerivedMesh *dm; struct vertexDupliData vdd; Scene *sce = NULL; Group *group = NULL; GroupObject * go = NULL; + EditMesh *em; + float vec[3], no[3], pmat[4][4]; + int lay, totvert, a, oblay; Mat4CpyMat4(pmat, par->obmat); /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; - - if(par==G.obedit) - dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); - else - dm= mesh_get_derived_deform(par, CD_MASK_BAREMESH); - + + em = BKE_mesh_get_editmesh(me); + + if(em) { + dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); + BKE_mesh_end_editmesh(me, em); + } else + dm= mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); + if(G.rendering) { - me= par->data; vdd.orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, vdd.orco, me->totvert, 0); } @@ -488,7 +497,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ oblay = ob_iter->lay; } - if (lay & oblay && G.obedit!=ob_iter) { + if (lay & oblay && scene->obedit!=ob_iter) { ob=ob_iter->parent; while(ob) { if(ob==par) { @@ -509,13 +518,14 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ vdd.animated= animated; vdd.lb= lb; vdd.ob= ob; + vdd.scene= scene; vdd.par= par; Mat4CpyMat4(vdd.pmat, pmat); /* mballs have a different dupli handling */ if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - if(par==G.obedit) { + if(par==scene->obedit) { dm->foreachMappedVert(dm, vertex_dupli__mapFunc, (void*) &vdd); } else { @@ -541,13 +551,13 @@ static void vertex_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], int level, int animated) +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int level, int animated) { Object *ob, *ob_iter; Base *base = NULL; DupliObject *dob; DerivedMesh *dm; - Mesh *me; + Mesh *me= par->data; MTFace *mtface; MFace *mface; MVert *mvert; @@ -556,16 +566,19 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma Scene *sce = NULL; Group *group = NULL; GroupObject *go = NULL; + EditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ /* simple preventing of too deep nested groups */ if(level>MAX_DUPLI_RECUR) return; Mat4CpyMat4(pmat, par->obmat); - - if(par==G.obedit) { + + em = BKE_mesh_get_editmesh(me); + if(em) { int totvert; - dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); + + dm= editmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp"); @@ -573,9 +586,11 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma totvert= dm->getNumVerts(dm); mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp"); dm->copyVertArray(dm, mvert); + + BKE_mesh_end_editmesh(me, em); } else { - dm = mesh_get_derived_deform(par, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH); totface= dm->getNumFaces(dm); mface= dm->getFaceArray(dm); @@ -583,7 +598,6 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma } if(G.rendering) { - me= (Mesh*)par->data; orco= (float(*)[3])get_mesh_orco_verts(par); transform_mesh_orco_verts(me, orco, me->totvert, 0); @@ -615,7 +629,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma oblay = ob_iter->lay; } - if (lay & oblay && G.obedit!=ob_iter) { + if (lay & oblay && scene->obedit!=ob_iter) { ob=ob_iter->parent; while(ob) { if(ob==par) { @@ -708,7 +722,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma float tmpmat[4][4]; Mat4CpyMat4(tmpmat, ob->obmat); Mat4CpyMat4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, ob, lb, ob->obmat, level+1, animated); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, level+1, animated); Mat4CpyMat4(ob->obmat, tmpmat); } } @@ -722,7 +736,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma else go= go->next; /* group loop */ } - if(par==G.obedit) { + if(par==scene->obedit) { MEM_freeN(mface); MEM_freeN(mvert); } @@ -733,7 +747,7 @@ static void face_duplilist(ListBase *lb, ID *id, Object *par, float par_space_ma dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], ParticleSystem *psys, int level, int animated) { GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; @@ -747,7 +761,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; - int lay, a, b, k, counter, hair = 0; + int lay, a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; if(psys==0) return; @@ -764,14 +778,14 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ if(!psys_check_enabled(par, psys)) return; - ctime = bsystem_time(par, (float)G.scene->r.cfra, 0.0); + ctime = bsystem_time(scene, par, (float)scene->r.cfra, 0.0); totpart = psys->totpart; totchild = psys->totchild; BLI_srandom(31415926 + psys->seed); - lay= G.scene->lay; + lay= scene->lay; if((part->draw_as == PART_DRAW_OB && part->dup_ob) || (part->draw_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first)) { @@ -787,11 +801,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ totpart = psys->totcached; } - psys->lattice = psys_get_lattice(par, psys); + psys->lattice = psys_get_lattice(scene, par, psys); /* gather list of objects or single object */ if(part->draw_as==PART_DRAW_GR) { - group_handle_recalc_and_update(par, part->dup_group); + group_handle_recalc_and_update(scene, par, part->dup_group); for(go=part->dup_group->gobject.first; go; go=go->next) totgroup++; @@ -872,7 +886,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ else { /* first key */ state.time = ctime; - if(psys_get_particle_state(par, psys, a, &state, 0) == 0) + if(psys_get_particle_state(scene, par, psys, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); @@ -897,7 +911,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } else { /* to give ipos in object correct offset */ - where_is_object_time(ob, ctime-pa_time); + where_is_object_time(scene, ob, ctime-pa_time); Mat4CpyMat4(mat, pamat); @@ -931,8 +945,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ MEM_freeN(obcopylist); if(psys->lattice) { - end_latt_deform(); - psys->lattice = 0; + end_latt_deform(psys->lattice); + psys->lattice = NULL; } } @@ -941,7 +955,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) Object *ob; int flen; - if( obar[ch] ) return obar[ch]; + if( obar[(int)ch] ) return obar[(int)ch]; flen= strlen(family); @@ -953,13 +967,13 @@ static Object *find_family_object(Object **obar, char *family, char ch) ob= ob->id.next; } - obar[ch]= ob; + obar[(int)ch]= ob; return ob; } -static void font_duplilist(ListBase *lb, Object *par, int level, int animated) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int level, int animated) { Object *ob, *obar[256]; Curve *cu; @@ -974,7 +988,7 @@ static void font_duplilist(ListBase *lb, Object *par, int level, int animated) /* in par the family name is stored, use this to find the other objects */ - chartransdata= text_to_curve(par, FO_DUPLI); + chartransdata= BKE_text_to_curve(scene, par, FO_DUPLI); if(chartransdata==0) return; memset(obar, 0, 256*sizeof(void *)); @@ -1008,7 +1022,7 @@ static void font_duplilist(ListBase *lb, Object *par, int level, int animated) } /* ***************************** */ -static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int level, int animated) { if((ob->transflag & OB_DUPLI)==0) return; @@ -1027,30 +1041,30 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, if(ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; for(; psys; psys=psys->next) - new_particle_duplilist(duplilist, id, ob, par_space_mat, psys, level+1, animated); + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, psys, level+1, animated); } else if(ob->transflag & OB_DUPLIVERTS) { if(ob->type==OB_MESH) { - vertex_duplilist(duplilist, id, ob, par_space_mat, level+1, animated); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, level+1, animated); } else if(ob->type==OB_FONT) { if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, ob, level+1, animated); + font_duplilist(duplilist, scene, ob, level+1, animated); } } } else if(ob->transflag & OB_DUPLIFACES) { if(ob->type==OB_MESH) - face_duplilist(duplilist, id, ob, par_space_mat, level+1, animated); + face_duplilist(duplilist, id, scene, ob, par_space_mat, level+1, animated); } else if(ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name)==ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, ob, level+1, animated); + frames_duplilist(duplilist, scene, ob, level+1, animated); } } else if(ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, ob, level+1, animated); /* now recursive */ + group_duplilist(duplilist, scene, ob, level+1, animated); /* now recursive */ if (level==0) { for(dob= duplilist->first; dob; dob= dob->next) @@ -1066,7 +1080,7 @@ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); duplilist->first= duplilist->last= NULL; - object_duplilist_recursive((ID *)sce, ob, duplilist, NULL, 0, 0); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0); return duplilist; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c new file mode 100644 index 00000000000..30dcb383ef6 --- /dev/null +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -0,0 +1,899 @@ +/* Testing code for new animation system in 2.5 + * Copyright 2009, Joshua Leung + */ + +#include <stdio.h> +#include <string.h> +#include <stddef.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_dynstr.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#include "DNA_anim_types.h" + +/* ***************************************** */ +/* AnimData API */ + +/* Getter/Setter -------------------------------------------- */ + +/* Internal utility to check if ID can have AnimData */ +static short id_has_animdata (ID *id) +{ + /* sanity check */ + if (id == NULL) + return 0; + + /* Only some ID-blocks have this info for now */ + // TODO: finish adding this for the other blocktypes + switch (GS(id->name)) { + /* has AnimData */ + case ID_OB: + case ID_CU: + case ID_KE: + case ID_MA: case ID_TE: case ID_NT: + case ID_LA: case ID_CA: case ID_WO: + case ID_SCE: + { + return 1; + } + + /* no AnimData */ + default: + return 0; + } +} + + +/* Get AnimData from the given ID-block. In order for this to work, we assume that + * the AnimData pointer is stored immediately after the given ID-block in the struct, + * as per IdAdtTemplate. + */ +AnimData *BKE_animdata_from_id (ID *id) +{ + /* only some ID-blocks have this info for now, so we cast the + * types that do to be of type IdAdtTemplate, and extract the + * AnimData that way + */ + if (id_has_animdata(id)) { + IdAdtTemplate *iat= (IdAdtTemplate *)id; + return iat->adt; + } + else + return NULL; +} + +/* Add AnimData to the given ID-block. In order for this to work, we assume that + * the AnimData pointer is stored immediately after the given ID-block in the struct, + * as per IdAdtTemplate. Also note that + */ +AnimData *BKE_id_add_animdata (ID *id) +{ + /* Only some ID-blocks have this info for now, so we cast the + * types that do to be of type IdAdtTemplate, and add the AnimData + * to it using the template + */ + if (id_has_animdata(id)) { + IdAdtTemplate *iat= (IdAdtTemplate *)id; + + /* check if there's already AnimData, in which case, don't add */ + if (iat->adt == NULL) + iat->adt= MEM_callocN(sizeof(AnimData), "AnimData"); + + return iat->adt; + } + else + return NULL; +} + +/* Freeing -------------------------------------------- */ + +/* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */ +void BKE_free_animdata (ID *id) +{ + /* Only some ID-blocks have this info for now, so we cast the + * types that do to be of type IdAdtTemplate + */ + if (id_has_animdata(id)) { + IdAdtTemplate *iat= (IdAdtTemplate *)id; + AnimData *adt= iat->adt; + + /* check if there's any AnimData to start with */ + if (adt) { + /* unlink action (don't free, as it's in its own list) */ + if (adt->action) + adt->action->id.us--; + + /* free drivers - stored as a list of F-Curves */ + free_fcurves(&adt->drivers); + + /* free overrides */ + // TODO... + + /* free animdata now */ + MEM_freeN(adt); + iat->adt= NULL; + } + } +} + +/* Freeing -------------------------------------------- */ + +/* Make a copy of the given AnimData - to be used when copying datablocks */ +AnimData *BKE_copy_animdata (AnimData *adt) +{ + AnimData *dadt; + + /* sanity check before duplicating struct */ + if (adt == NULL) + return NULL; + dadt= MEM_dupallocN(adt); + + /* make a copy of action - at worst, user has to delete copies... */ + // XXX review this... it might not be optimal behaviour yet... + //id_us_plus((ID *)dadt->action); + dadt->action= copy_action(adt->action); + + /* duplicate NLA data */ + // XXX todo... + + /* duplicate drivers (F-Curves) */ + copy_fcurves(&dadt->drivers, &adt->drivers); + + /* don't copy overrides */ + dadt->overrides.first= dadt->overrides.last= NULL; + + /* return */ + return dadt; +} + +/* *********************************** */ +/* KeyingSet API */ + +/* NOTES: + * It is very likely that there will be two copies of the api - one for internal use, + * and one 'operator' based wrapper of the internal API, which should allow for access + * from Python/scripts so that riggers can automate the creation of KeyingSets for their rigs. + */ + +/* Finding Tools --------------------------- */ + +/* Find the first path that matches the given criteria */ +// TODO: do we want some method to perform partial matches too? +KS_Path *BKE_keyingset_find_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode) +{ + KS_Path *ksp; + + /* sanity checks */ + if ELEM(NULL, ks, rna_path) + return NULL; + + /* ID is optional for relative KeyingSets, but is necessary for absolute KeyingSets */ + if (id == NULL) { + if (ks->flag & KEYINGSET_ABSOLUTE) + return NULL; + } + + /* loop over paths in the current KeyingSet, finding the first one where all settings match + * (i.e. the first one where none of the checks fail and equal 0) + */ + for (ksp= ks->paths.first; ksp; ksp= ksp->next) { + short eq_id=1, eq_path=1, eq_index=1, eq_group=1; + + /* id */ + if ((ks->flag & KEYINGSET_ABSOLUTE) && (id != ksp->id)) + eq_id= 0; + + /* path */ + if ((ksp->rna_path==0) || strcmp(rna_path, ksp->rna_path)) + eq_path= 0; + + /* index */ + if (ksp->array_index != array_index) + eq_index= 0; + + /* group */ + if (group_name) { + // FIXME: these checks need to be coded... for now, it's not too important though + } + + /* if all aspects are ok, return */ + if (eq_id && eq_path && eq_index && eq_group) + return ksp; + } + + /* none found */ + return NULL; +} + +/* Defining Tools --------------------------- */ + +/* Used to create a new 'custom' KeyingSet for the user, that will be automatically added to the stack */ +KeyingSet *BKE_keyingset_add (ListBase *list, const char name[], short flag, short keyingflag) +{ + KeyingSet *ks; + + /* allocate new KeyingSet */ + ks= MEM_callocN(sizeof(KeyingSet), "KeyingSet"); + + if (name) + BLI_snprintf(ks->name, 64, name); + else + strcpy(ks->name, "Keying Set"); + + ks->flag= flag; + ks->keyingflag= keyingflag; + + /* add KeyingSet to list */ + BLI_addtail(list, ks); + + /* make sure KeyingSet has a unique name (this helps with identification) */ + BLI_uniquename(list, ks, "Keying Set", ' ', offsetof(KeyingSet, name), 64); + + /* return new KeyingSet for further editing */ + return ks; +} + +/* Add a destination to a KeyingSet. Nothing is returned for now... + * Checks are performed to ensure that destination is appropriate for the KeyingSet in question + */ +void BKE_keyingset_add_destination (KeyingSet *ks, ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode) +{ + KS_Path *ksp; + + /* sanity checks */ + if ELEM(NULL, ks, rna_path) + return; + + /* ID is optional for relative KeyingSets, but is necessary for absolute KeyingSets */ + if (id == NULL) { + if (ks->flag & KEYINGSET_ABSOLUTE) + return; + } + + /* don't add if there is already a matching KS_Path in the KeyingSet */ + if (BKE_keyingset_find_destination(ks, id, group_name, rna_path, array_index, groupmode)) + return; + + /* allocate a new KeyingSet Path */ + ksp= MEM_callocN(sizeof(KS_Path), "KeyingSet Path"); + + /* just store absolute info */ + if (ks->flag & KEYINGSET_ABSOLUTE) { + ksp->id= id; + if (group_name) + BLI_snprintf(ksp->group, 64, group_name); + else + strcpy(ksp->group, ""); + } + + /* store additional info for relative paths (just in case user makes the set relative) */ + if (id) + ksp->idtype= GS(id->name); + + /* just copy path info */ + // XXX no checks are performed for templates yet + // should array index be checked too? + ksp->rna_path= BLI_strdupn(rna_path, strlen(rna_path)); + ksp->array_index= array_index; + + /* store flags */ + ksp->flag= flag; + ksp->groupmode= groupmode; + + /* add KeyingSet path to KeyingSet */ + BLI_addtail(&ks->paths, ksp); +} + + +/* Freeing Tools --------------------------- */ + +/* Free data for KeyingSet but not set itself */ +void BKE_keyingset_free (KeyingSet *ks) +{ + KS_Path *ksp, *kspn; + + /* sanity check */ + if (ks == NULL) + return; + + /* free each path as we go to avoid looping twice */ + for (ksp= ks->paths.first; ksp; ksp= kspn) { + kspn= ksp->next; + + /* free RNA-path info */ + MEM_freeN(ksp->rna_path); + + /* free path itself */ + BLI_freelinkN(&ks->paths, ksp); + } +} + +/* Free all the KeyingSets in the given list */ +void BKE_keyingsets_free (ListBase *list) +{ + KeyingSet *ks, *ksn; + + /* sanity check */ + if (list == NULL) + return; + + /* loop over KeyingSets freeing them + * - BKE_keyingset_free() doesn't free the set itself, but it frees its sub-data + */ + for (ks= list->first; ks; ks= ksn) { + ksn= ks->next; + BKE_keyingset_free(ks); + BLI_freelinkN(list, ks); + } +} + +/* ***************************************** */ +/* Evaluation Data-Setting Backend */ + +/* Retrieve string to act as RNA-path, adjusted using mapping-table if provided + * It returns whether the string needs to be freed (i.e. if it was a temp remapped one) + * // FIXME: maybe it would be faster if we didn't have to alloc/free strings like this all the time, but for now it's safer + * + * - remap: remapping table to use + * - path: original path string (as stored in F-Curve data) + * - dst: destination string to write data to + */ +short animsys_remap_path (AnimMapper *remap, char *path, char **dst) +{ + /* is there a valid remapping table to use? */ + if (remap) { + /* find a matching entry... to use to remap */ + // ...TODO... + } + + /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ + *dst= path; + return 0; +} + + +/* Write the given value to a setting using RNA, and return success */ +static short animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_index, float value) +{ + PropertyRNA *prop; + PointerRNA new_ptr; + + /* get property to write to */ + if (RNA_path_resolve(ptr, path, &new_ptr, &prop)) + { + /* set value - only for animatable numerical values */ + if (RNA_property_animateable(&new_ptr, prop)) + { + switch (RNA_property_type(prop)) + { + case PROP_BOOLEAN: + if (RNA_property_array_length(prop)) + RNA_property_boolean_set_index(&new_ptr, prop, array_index, (int)value); + else + RNA_property_boolean_set(&new_ptr, prop, (int)value); + break; + case PROP_INT: + if (RNA_property_array_length(prop)) + RNA_property_int_set_index(&new_ptr, prop, array_index, (int)value); + else + RNA_property_int_set(&new_ptr, prop, (int)value); + break; + case PROP_FLOAT: + if (RNA_property_array_length(prop)) + RNA_property_float_set_index(&new_ptr, prop, array_index, value); + else + RNA_property_float_set(&new_ptr, prop, value); + break; + case PROP_ENUM: + RNA_property_enum_set(&new_ptr, prop, (int)value); + break; + default: + /* nothing can be done here... so it is unsuccessful? */ + return 0; + } + } + + /* successful */ + return 1; + } + else { + /* failed to get path */ + // XXX don't tag as failed yet though, as there are some legit situations (Action Constraint) + // where some channels will not exist, but shouldn't lock up Action + if (G.f & G_DEBUG) { + printf("Animato: Invalid path. ID = '%s', '%s [%d]' \n", + (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name+2) : "<No ID>", + path, array_index); + } + return 0; + } +} + +/* Simple replacement based data-setting of the FCurve using RNA */ +static short animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve *fcu) +{ + char *path = NULL; + short free_path=0; + short ok= 0; + + /* get path, remapped as appropriate to work in its new environment */ + free_path= animsys_remap_path(remap, fcu->rna_path, &path); + + /* write value to setting */ + if (path) + ok= animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval); + + /* free temp path-info */ + if (free_path) + MEM_freeN(path); + + /* return whether we were successful */ + return ok; +} + +/* Evaluate all the F-Curves in the given list + * This performs a set of standard checks. If extra checks are required, separate code should be used + */ +static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime) +{ + FCurve *fcu; + + /* calculate then execute each curve */ + for (fcu= list->first; fcu; fcu= fcu->next) + { + /* check if this curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + calculate_fcurve(fcu, ctime); + animsys_execute_fcurve(ptr, remap, fcu); + } + } +} + +/* ***************************************** */ +/* Driver Evaluation */ + +/* Evaluate Drivers */ +static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctime) +{ + FCurve *fcu; + + /* drivers are stored as F-Curves, but we cannot use the standard code, as we need to check if + * the depsgraph requested that this driver be evaluated... + */ + for (fcu= adt->drivers.first; fcu; fcu= fcu->next) + { + ChannelDriver *driver= fcu->driver; + short ok= 0; + + /* check if this driver's curve should be skipped */ + // FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable? + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + /* check if driver itself is tagged for recalculation */ + if ((driver) && !(driver->flag & DRIVER_FLAG_INVALID)/*&& (driver->flag & DRIVER_FLAG_RECALC)*/) { // XXX driver recalc flag is not set yet by depsgraph! + /* evaluate this using values set already in other places */ + // NOTE: for 'layering' option later on, we should check if we should remove old value before adding new to only be done when drivers only changed + calculate_fcurve(fcu, ctime); + ok= animsys_execute_fcurve(ptr, NULL, fcu); + + /* clear recalc flag */ + driver->flag &= ~DRIVER_FLAG_RECALC; + + /* set error-flag if evaluation failed */ + if (ok == 0) + driver->flag |= DRIVER_FLAG_INVALID; + } + } + } +} + +/* ***************************************** */ +/* Actions Evaluation */ + +/* Evaluate Action Group */ +void animsys_evaluate_action_group (PointerRNA *ptr, bAction *act, bActionGroup *agrp, AnimMapper *remap, float ctime) +{ + FCurve *fcu; + + /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ + if ELEM(NULL, act, agrp) return; + if ((remap) && (remap->target != act)) remap= NULL; + + /* calculate then execute each curve */ + for (fcu= agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu= fcu->next) + { + /* check if this curve should be skipped */ + if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0) + { + calculate_fcurve(fcu, ctime); + animsys_execute_fcurve(ptr, remap, fcu); + } + } +} + +/* Evaluate Action (F-Curve Bag) */ +void animsys_evaluate_action (PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) +{ + /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ + if (act == NULL) return; + if ((remap) && (remap->target != act)) remap= NULL; + + /* calculate then execute each curve */ + animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime); +} + +/* ***************************************** */ +/* NLA System - Evaluation */ + +/* used for list of strips to accumulate at current time */ +typedef struct NlaEvalStrip { + struct NlaEvalStrip *next, *prev; + + NlaTrack *track; /* track that this strip belongs to */ + NlaStrip *strip; /* strip that's being used */ + NlaStrip *sblend; /* strip that's being blended towards (if applicable) */ + + short track_index; /* the index of the track within the list */ + short strip_mode; /* which end of the strip are we looking at */ +} NlaEvalStrip; + +/* bNlaEvalStrip->strip_mode */ +enum { + NES_TIME_BEFORE = -1, + NES_TIME_WITHIN, + NES_TIME_AFTER, + NES_TIME_AFTER_BLEND +} eNlaEvalStrip_StripMode; + + +/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */ +// TODO: maybe this will be used as the 'cache' stuff needed for editable values too? +typedef struct NlaEvalChannel { + struct NlaEvalChannel *next, *prev; + + char *path; /* ready-to-use path (i.e. remapped already) */ + int array_index; /* if applicable... */ + + float value; /* value of this channel */ +} NlaEvalChannel; + + +/* ---------------------- */ + +/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */ +static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime) +{ + //PointerRNA actstrip_ptr; + //FCurve *fcu; + + /* create RNA-pointer needed to set values */ + //RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr); + + /* execute these settings as per normal */ + //animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime); +} + + +/* gets the strip active at the current time for a track */ +static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime) +{ + NlaStrip *strip, *astrip=NULL, *bstrip=NULL; + NlaEvalStrip *nes; + short side= 0; + + /* skip if track is muted */ + if (nlt->flag & NLATRACK_MUTED) + return; + + /* loop over strips, checking if they fall within the range */ + for (strip= nlt->strips.first; strip; strip= strip->next) { + /* only consider if: + * - current time occurs within strip's extents + * - current time occurs before strip (if it is the first) + * - current time occurs after strip (if hold is on) + * - current time occurs between strips (1st of those isn't holding) - blend! + */ + if (IN_RANGE(ctime, strip->start, strip->end)) { + astrip= strip; + side= NES_TIME_WITHIN; + break; + } + else if (ctime < strip->start) { + if (strip == nlt->strips.first) { + astrip= strip; + side= NES_TIME_BEFORE; + break; + } + else { + astrip= strip->prev; + + if (astrip->flag & NLASTRIP_HOLDLASTFRAME) { + side= NES_TIME_AFTER; + break; + } + else { + bstrip= strip; + side= NES_TIME_AFTER_BLEND; + break; + } + } + } + } + + /* check if strip has been found (and whether it has data worth considering) */ + if (ELEM(NULL, astrip, astrip->act)) + return; + if (astrip->flag & NLASTRIP_MUTE) + return; + + /* check if blending between strips */ + if (side == NES_TIME_AFTER_BLEND) { + /* blending between strips... so calculate influence+act_time of both */ + nlastrip_evaluate_fcurves(astrip, ctime); + nlastrip_evaluate_fcurves(bstrip, ctime); + + if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f)) + return; + } + else { + /* calculate/set the influence+act_time of this strip - don't consider if 0 influence */ + nlastrip_evaluate_fcurves(astrip, ctime); + + if (astrip->influence <= 0.0f) + return; + } + + + /* allocate new eval-strip for this strip + add to stack */ + nes= MEM_callocN(sizeof(NlaEvalStrip), "NlaEvalStrip"); + + nes->track= nlt; + nes->strip= astrip; + nes->sblend= bstrip; + nes->track_index= index; + nes->strip_mode= side; + + BLI_addtail(list, nes); +} + +/* ---------------------- */ + +/* evaluates the given evaluation strip */ +// FIXME: will we need the evaluation cache table set up to blend stuff in? +// TODO: only evaluate here, but flush in one go using the accumulated channels at end... +static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime) +{ + // 1. (in old code) was to extract 'IPO-channels' from actions + // 2. blend between the 'accumulated' data, and the new data +} + +/* write the accumulated settings to */ +static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels) +{ + +} + +/* ---------------------- */ + +/* NLA Evaluation function (mostly for use through do_animdata) + * - All channels that will be affected are not cleared anymore. Instead, we just evaluate into + * some temp channels, where values can be accumulated in one go. + */ +static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime) +{ + NlaTrack *nlt; + short track_index=0; + + ListBase estrips= {NULL, NULL}; + ListBase echannels= {NULL, NULL}; + NlaEvalStrip *nes; + + /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ + for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++) + nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime); + + /* only continue if there are strips to evaluate */ + if (estrips.first == NULL) + return; + + + /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */ + for (nes= estrips.first; nes; nes= nes->next) + nlastrip_ctime_evaluate(&echannels, nes, ctime); + + /* 3. flush effects of accumulating channels in NLA to the actual data they affect */ + nladata_flush_channels(ptr, &echannels); + + /* 4. free temporary evaluation data */ + BLI_freelistN(&estrips); + BLI_freelistN(&echannels); +} + +/* ***************************************** */ +/* Overrides System - Public API */ + +/* Clear all overides */ + +/* Add or get existing Override for given setting */ +AnimOverride *BKE_animsys_validate_override (PointerRNA *ptr, char *path, int array_index) +{ + // FIXME: need to define how to get overrides + return NULL; +} + +/* -------------------- */ + +/* Evaluate Overrides */ +static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ctime) +{ + AnimOverride *aor; + + /* for each override, simply execute... */ + for (aor= adt->overrides.first; aor; aor= aor->next) + animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value); +} + +/* ***************************************** */ +/* Evaluation System - Public API */ + +/* Overview of how this system works: + * 1) Depsgraph sorts data as necessary, so that data is in an order that means + * that all dependences are resolved before dependants. + * 2) All normal animation is evaluated, so that drivers have some basis values to + * work with + * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks + * which modify the effects of the NLA-stacks + * b. Active Action is evaluated as per normal, on top of the results of the NLA tracks + * + * --------------< often in a separate phase... >------------------ + * + * 3) Drivers/expressions are evaluated on top of this, in an order where dependences are + * resolved nicely. + * Note: it may be necessary to have some tools to handle the cases where some higher-level + * drivers are added and cause some problematic dependencies that didn't exist in the local levels... + * + * --------------< always executed >------------------ + * + * Maintainance of editability of settings (XXX): + * In order to ensure that settings that are animated can still be manipulated in the UI without requiring + * that keyframes are added to prevent these values from being overwritten, we use 'overrides'. + * + * Unresolved things: + * - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids or nodal system? but stored where? + * - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists? + */ + +/* Evaluation loop for evaluation animation data + * + * This assumes that the animation-data provided belongs to the ID block in question, + * and that the flags for which parts of the anim-data settings need to be recalculated + * have been set already by the depsgraph. Now, we use the recalc + */ +void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short recalc) +{ + PointerRNA id_ptr; + + /* sanity checks */ + if ELEM(NULL, id, adt) + return; + + /* get pointer to ID-block for RNA to use */ + RNA_id_pointer_create(id, &id_ptr); + + /* recalculate keyframe data: + * - NLA before Active Action, as Active Action behaves as 'tweaking track' + * that overrides 'rough' work in NLA + */ + if ((recalc & ADT_RECALC_ANIM) || (adt->recalc & ADT_RECALC_ANIM)) + { + /* evaluate NLA data */ + if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF)) + { + animsys_evaluate_nla(&id_ptr, adt, ctime); + } + + /* evaluate Action data */ + // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too? + if (adt->action) + animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); + + /* reset tag */ + adt->recalc &= ~ADT_RECALC_ANIM; + } + + /* recalculate drivers + * - Drivers need to be evaluated afterwards, as they can either override + * or be layered on top of existing animation data. + * - Drivers should be in the appropriate order to be evaluated without problems... + */ + if ((recalc & ADT_RECALC_DRIVERS) /*&& (adt->recalc & ADT_RECALC_DRIVERS)*/) // XXX for now, don't check yet, as depsgraph hasn't been updated + { + animsys_evaluate_drivers(&id_ptr, adt, ctime); + } + + /* always execute 'overrides' + * - Overrides allow editing, by overwriting the value(s) set from animation-data, with the + * value last set by the user (and not keyframed yet). + * - Overrides are cleared upon frame change and/or keyframing + * - It is best that we execute this everytime, so that no errors are likely to occur. + */ + animsys_evaluate_overrides(&id_ptr, adt, ctime); + + /* clear recalc flag now */ + adt->recalc= 0; +} + +/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only + * + * This will evaluate only the animation info available in the animation data-blocks + * encountered. In order to enforce the system by which some settings controlled by a + * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a + * standard 'root') block are overridden by a larger 'user' + */ +// TODO: we currently go over entire 'main' database... +void BKE_animsys_evaluate_all_animation (Main *main, float ctime) +{ + ID *id; + + if (G.f & G_DEBUG) + printf("Evaluate all animation - %f \n", ctime); + + /* macro for less typing */ +#define EVAL_ANIM_IDS(first, flag) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, flag); \ + } + + /* nodes */ + // TODO... + + /* textures */ + EVAL_ANIM_IDS(main->tex.first, ADT_RECALC_ANIM); + + /* lamps */ + EVAL_ANIM_IDS(main->lamp.first, ADT_RECALC_ANIM); + + /* materials */ + EVAL_ANIM_IDS(main->mat.first, ADT_RECALC_ANIM); + + /* cameras */ + EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); + + /* shapekeys */ + EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); + + /* curves */ + // TODO... + + /* meshes */ + // TODO... + + /* objects */ + /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets + * this tagged by Depsgraph on framechange + */ + EVAL_ANIM_IDS(main->object.first, /*ADT_RECALC_ANIM*/0); + + /* worlds */ + EVAL_ANIM_IDS(main->world.first, ADT_RECALC_ANIM); + + /* scenes */ + EVAL_ANIM_IDS(main->scene.first, ADT_RECALC_ANIM); +} + +/* ***************************************** */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 155d5a7d21c..1b930a74449 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -34,7 +34,7 @@ #include "MEM_guardedalloc.h" -#include "nla.h" +//XXX #include "nla.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -67,7 +67,7 @@ #include "BKE_object.h" #include "BKE_utildefines.h" -#include "BIF_editdeform.h" +//XXX #include "BIF_editdeform.h" #include "IK_solver.h" @@ -77,13 +77,6 @@ /* **************** Generic Functions, data level *************** */ -bArmature *get_armature(Object *ob) -{ - if(ob==NULL) return NULL; - if(ob->type==OB_ARMATURE) return ob->data; - else return NULL; -} - bArmature *add_armature(char *name) { bArmature *arm; @@ -94,6 +87,12 @@ bArmature *add_armature(char *name) return arm; } +bArmature *get_armature(Object *ob) +{ + if(ob->type==OB_ARMATURE) + return (bArmature *)ob->data; + return NULL; +} void free_boneChildren(Bone *bone) { @@ -133,6 +132,14 @@ void free_armature(bArmature *arm) if (arm) { /* unlink_armature(arm);*/ free_bones(arm); + + /* free editmode data */ + if (arm->edbo) { + BLI_freelistN(arm->edbo); + + MEM_freeN(arm->edbo); + arm->edbo= NULL; + } } } @@ -180,7 +187,7 @@ static void copy_bonechildren (Bone* newBone, Bone* oldBone) Bone *curBone, *newChildBone; /* Copy this bone's list*/ - duplicatelist (&newBone->childbase, &oldBone->childbase); + BLI_duplicatelist(&newBone->childbase, &oldBone->childbase); /* For each child in the list, update it's children*/ newChildBone=newBone->childbase.first; @@ -197,7 +204,7 @@ bArmature *copy_armature(bArmature *arm) Bone *oldBone, *newBone; newArm= copy_libblock (arm); - duplicatelist(&newArm->bonebase, &arm->bonebase); + BLI_duplicatelist(&newArm->bonebase, &arm->bonebase); /* Duplicate the childrens' lists*/ newBone=newArm->bonebase.first; @@ -364,7 +371,7 @@ void bone_flip_name (char *name, int strip_number) */ void bone_autoside_name (char *name, int strip_number, short axis, float head, float tail) { - int len; + unsigned int len; char basename[32]={""}; char extension[5]={""}; @@ -607,7 +614,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) Mat3Inv(imat3, mat3); Mat3MulMat3(mat3, result, imat3); // the matrix transforming vec_roll to desired roll - roll1= atan2(mat3[2][0], mat3[2][2]); + roll1= (float)atan2(mat3[2][0], mat3[2][2]); } } else { @@ -640,7 +647,7 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) Mat3Inv(imat3, mat3); Mat3MulMat3(mat3, imat3, result); // the matrix transforming vec_roll to desired roll - roll2= atan2(mat3[2][0], mat3[2][2]); + roll2= (float)atan2(mat3[2][0], mat3[2][2]); /* and only now negate handle */ VecMulf(h2, -hlength2); @@ -785,7 +792,7 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl if(l!=0.0f) { rad= a/l; - rad= rad*rad2 + (1.0-rad)*rad1; + rad= rad*rad2 + (1.0f-rad)*rad1; } else rad= rad1; } @@ -799,8 +806,8 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl if(rdist==0.0f || dist >= l) return 0.0f; else { - a= sqrt(dist)-rad; - return 1.0-( a*a )/( rdist*rdist ); + a= (float)sqrt(dist)-rad; + return 1.0f-( a*a )/( rdist*rdist ); } } } @@ -906,6 +913,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, int numVerts, int deformflag, float (*prevCos)[3], const char *defgrp_name) { + bArmature *arm= armOb->data; bPoseChannel *pchan, **defnrToPC = NULL; MDeformVert *dverts = NULL; bDeformGroup *dg; @@ -921,7 +929,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, int armature_def_nr = -1; int totchan; - if(armOb == G.obedit) return; + if(arm->edbo) return; Mat4Invert(obinv, target->obmat); Mat4CpyMat4(premat, target->obmat); @@ -1216,7 +1224,10 @@ void armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[][4], float outm if (pchan==NULL) return; /* get the inverse matrix of the pchan's transforms */ - LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size); + if (pchan->rotmode) + LocEulSizeToMat4(pc_trans, pchan->loc, pchan->eul, pchan->size); + else + LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size); Mat4Invert(inv_trans, pc_trans); /* Remove the pchan's transforms from it's pose_mat. @@ -1298,7 +1309,7 @@ void mat3_to_vec_roll(float mat[][3], float *vec, float *roll) Mat3Inv(vecmatinv, vecmat); Mat3MulMat3(rollmat, vecmatinv, mat); - *roll= atan2(rollmat[2][0], rollmat[2][2]); + *roll= (float)atan2(rollmat[2][0], rollmat[2][2]); } } @@ -1330,7 +1341,7 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3]) float updown; /* point same direction, or opposite? */ - updown = ( Inpf (target,nor) > 0 ) ? 1.0 : -1.0; + updown = ( Inpf (target,nor) > 0 ) ? 1.0f : -1.0f; /* I think this should work ... */ bMatrix[0][0]=updown; bMatrix[0][1]=0.0; bMatrix[0][2]=0.0; @@ -1433,7 +1444,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected * so syncing things correctly needs careful attention */ BLI_freelistN(&pose->agroups); - duplicatelist(&pose->agroups, &frompose->agroups); + BLI_duplicatelist(&pose->agroups, &frompose->agroups); pose->active_group= frompose->active_group; for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { @@ -1568,7 +1579,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) PoseTree *tree; PoseTarget *target; bConstraint *con; - bKinematicConstraint *data; + bKinematicConstraint *data= NULL; int a, segcount= 0, size, newsize, *oldparent, parent; /* find IK constraint, and validate it */ @@ -1786,10 +1797,10 @@ static void execute_posetree(Object *ob, PoseTree *tree) IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); - if(tree->stretch && (pchan->ikstretch > 0.0)) { + if(tree->stretch && (pchan->ikstretch > 0.0f)) { float ikstretch = pchan->ikstretch*pchan->ikstretch; - IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.99)); - IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10); + IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f)); + IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10); } } @@ -1855,10 +1866,10 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* do we need blending? */ - if (!resultblend && target->con->enforce!=1.0) { + if (!resultblend && target->con->enforce!=1.0f) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; - float mfac= 1.0-fac; + float mfac= 1.0f-fac; pchan= tree->pchan[target->tip]; @@ -1881,13 +1892,13 @@ static void execute_posetree(Object *ob, PoseTree *tree) iktarget= iktree[target->tip]; - if(data->weight != 0.0) { + if(data->weight != 0.0f) { if(poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, - polepos, data->poleangle*M_PI/180, (poleangledata == data)); + polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data)); IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); } - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0)) + if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) if((data->flag & CONSTRAINT_IK_AUTO)==0) IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight); @@ -1897,7 +1908,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) IK_Solve(solver, 0.0f, tree->iterations); if(poleangledata) - poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180/M_PI; + poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180.0f/(float)M_PI; IK_FreeSolver(solver); @@ -1914,20 +1925,20 @@ static void execute_posetree(Object *ob, PoseTree *tree) float parentstretch, stretch; pchan= tree->pchan[a]; - parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0; + parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f; - if(tree->stretch && (pchan->ikstretch > 0.0)) { + if(tree->stretch && (pchan->ikstretch > 0.0f)) { float trans[3], length; IK_GetTranslationChange(iktree[a], trans); length= pchan->bone->length*VecLength(pchan->pose_mat[1]); - ikstretch[a]= (length == 0.0)? 1.0: (trans[1]+length)/length; + ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length; } else - ikstretch[a] = 1.0; + ikstretch[a] = 1.0f; - stretch= (parentstretch == 0.0)? 1.0: ikstretch[a]/parentstretch; + stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch; VecMulf(tree->basis_change[a][0], stretch); VecMulf(tree->basis_change[a][1], stretch); @@ -1967,22 +1978,29 @@ void chan_calc_mat(bPoseChannel *chan) float rmat[3][3]; float tmat[3][3]; + /* get scaling matrix */ SizeToMat3(chan->size, smat); - NormalQuat(chan->quat); - - QuatToMat3(chan->quat, rmat); + /* rotations may either be quats or eulers (no rotation modes for now...) */ + if (chan->rotmode) { + /* euler rotations (will cause gimble lock... no rotation order to solve that yet) */ + EulToMat3(chan->eul, rmat); + } + else { + /* quats are normalised before use to eliminate scaling issues */ + NormalQuat(chan->quat); + QuatToMat3(chan->quat, rmat); + } + /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */ Mat3MulMat3(tmat, rmat, smat); - Mat4CpyMat3(chan->chan_mat, tmat); /* prevent action channels breaking chains */ /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */ - if (chan->bone==NULL || !(chan->bone->flag & BONE_CONNECTED)) { + if ((chan->bone==NULL) || !(chan->bone->flag & BONE_CONNECTED)) { VECCOPY(chan->chan_mat[3], chan->loc); } - } /* transform from bone(b) to bone(b+1), store in chan_mat */ @@ -2021,11 +2039,11 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t } /* NLA strip modifiers */ -static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan) +static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan) { bActionModifier *amod; bActionStrip *strip, *strip2; - float scene_cfra= G.scene->r.cfra; + float scene_cfra= (float)scene->r.cfra; int do_modif; for (strip=armob->nlastrips.first; strip; strip=strip->next) { @@ -2074,7 +2092,7 @@ static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan) if( strcmp(pchan->name, amod->channel)==0 ) { float mat4[4][4], mat3[3][3]; - curve_deform_vector(amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis); + curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis); Mat4CpyMat4(mat4, pchan->pose_mat); Mat4MulMat34(pchan->pose_mat, mat3, mat4); @@ -2145,7 +2163,7 @@ static void do_strip_modifiers(Object *armob, Bone *bone, bPoseChannel *pchan) /* The main armature solver, does all constraints excluding IK */ /* pchan is validated, as having bone and parent pointer */ -static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime) +static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) { Bone *bone, *parbone; bPoseChannel *parchan; @@ -2215,22 +2233,19 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime) } /* do NLA strip modifiers - i.e. curve follow */ - do_strip_modifiers(ob, bone, pchan); + do_strip_modifiers(scene, ob, bone, pchan); /* Do constraints */ if (pchan->constraints.first) { bConstraintOb *cob; - /* local constraints */ - do_constraint_channels(&pchan->constraints, NULL, ctime, 0); - /* make a copy of location of PoseChannel for later */ VECCOPY(vec, pchan->pose_mat[3]); /* prepare PoseChannel for Constraint solving * - makes a copy of matrix, and creates temporary struct to use */ - cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE); + cob= constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); /* Solve PoseChannel's Constraints */ solve_constraints(&pchan->constraints, cob, ctime); // ctime doesnt alter objects @@ -2256,22 +2271,25 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime) /* This only reads anim data from channels, and writes to channels */ /* This is the only function adding poses */ -void where_is_pose (Object *ob) +void where_is_pose (Scene *scene, Object *ob) { bArmature *arm; Bone *bone; bPoseChannel *pchan; float imat[4][4]; - float ctime= bsystem_time(ob, (float)G.scene->r.cfra, 0.0); /* not accurate... */ + float ctime; - arm = get_armature(ob); + if(ob->type!=OB_ARMATURE) return; + arm = ob->data; - if(arm==NULL) return; - if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) + if(ELEM(NULL, arm, scene)) return; + if((ob->pose==NULL) || (ob->pose->flag & POSE_RECALC)) armature_rebuild_pose(ob, arm); + + ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); /* not accurate... */ - /* In restposition we read the data from the bones */ - if(ob==G.obedit || (arm->flag & ARM_RESTPOS)) { + /* In editmode or restposition we read the data from the bones */ + if(arm->edbo || (arm->flag & ARM_RESTPOS)) { for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { bone= pchan->bone; @@ -2304,7 +2322,7 @@ void where_is_pose (Object *ob) /* 4. walk over the tree for regular solving */ for(a=0; a<tree->totchannel; a++) { if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag - where_is_pose_bone(ob, tree->pchan[a], ctime); + where_is_pose_bone(scene, ob, tree->pchan[a], ctime); } /* 5. execute the IK solver */ execute_posetree(ob, tree); @@ -2324,7 +2342,7 @@ void where_is_pose (Object *ob) } } else if(!(pchan->flag & POSE_DONE)) { - where_is_pose_bone(ob, pchan, ctime); + where_is_pose_bone(scene, ob, pchan, ctime); } } } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 5dcccc56d06..5fc7d18689d 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -48,12 +48,16 @@ #include "MEM_guardedalloc.h" +#include "DNA_curve_types.h" #include "DNA_listBase.h" #include "DNA_sdna_types.h" #include "DNA_userdef_types.h" #include "DNA_object_types.h" -#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_sound_types.h" +#include "DNA_sequence_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" @@ -61,21 +65,24 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "DNA_mesh_types.h" -#include "DNA_screen_types.h" - +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_blender.h" +#include "BKE_context.h" #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_ipo.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_sequence.h" #include "BKE_sound.h" #include "BLI_editVert.h" @@ -84,15 +91,12 @@ #include "BLO_readfile.h" #include "BLO_writefile.h" -#include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature #include "BKE_utildefines.h" // O_BINARY FALSE -#include "BIF_mainqueue.h" // mainqenter for onload script -#include "mydevice.h" -#include "nla.h" -#include "blendef.h" Global G; UserDef U; +ListBase WMlist= {NULL, NULL}; +short ENDIAN_ORDER; char versionstr[48]= ""; @@ -168,6 +172,7 @@ void pushpop_test() /* ********** free ********** */ +/* only to be called on exit blender */ void free_blender(void) { /* samples are in a global list..., also sets G.main->sound->sample NULL */ @@ -176,58 +181,35 @@ void free_blender(void) free_main(G.main); G.main= NULL; + BKE_spacetypes_free(); /* after free main, it uses space callbacks */ + IMB_freeImBufdata(); /* imbuf lib */ free_nodesystem(); } -void duplicatelist(ListBase *list1, ListBase *list2) /* copy from 2 to 1 */ -{ - struct Link *link1, *link2; - - list1->first= list1->last= 0; - - link2= list2->first; - while(link2) { - - link1= MEM_dupallocN(link2); - BLI_addtail(list1, link1); - - link2= link2->next; - } -} - -static EditMesh theEditMesh; - void initglobals(void) { memset(&G, 0, sizeof(Global)); - memset(&theEditMesh, 0, sizeof(theEditMesh)); - G.editMesh = &theEditMesh; - U.savetime= 1; G.main= MEM_callocN(sizeof(Main), "initglobals"); strcpy(G.ima, "//"); - G.version= BLENDER_VERSION; - - G.order= 1; - G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN; + ENDIAN_ORDER= 1; + ENDIAN_ORDER= (((char*)&ENDIAN_ORDER)[0])? L_ENDIAN: B_ENDIAN; if(BLENDER_SUBVERSION) - sprintf(versionstr, "www.blender.org %d.%d", G.version, BLENDER_SUBVERSION); + sprintf(versionstr, "www.blender.org %d.%d", BLENDER_VERSION, BLENDER_SUBVERSION); else - sprintf(versionstr, "www.blender.org %d", G.version); + sprintf(versionstr, "www.blender.org %d", BLENDER_VERSION); #ifdef _WIN32 // FULLSCREEN G.windowstate = G_WINDOWSTATE_USERDEF; #endif - clear_workob(); /* object.c */ - G.charstart = 0x0000; G.charmin = 0x0000; G.charmax = 0xffff; @@ -237,37 +219,16 @@ void initglobals(void) static void clear_global(void) { - extern short winqueue_break; /* screen.c */ +// extern short winqueue_break; /* screen.c */ - freeAllRad(); +// XXX freeAllRad(); fastshade_free_render(); /* lamps hang otherwise */ free_main(G.main); /* free all lib data */ - - /* force all queues to be left */ - winqueue_break= 1; - if (G.obedit) { - freeNurblist(&editNurb); - free_editMesh(G.editMesh); - free_editText(); - free_editArmature(); - } +// free_vertexpaint(); - G.curscreen= NULL; - G.scene= NULL; G.main= NULL; - G.obedit= NULL; - G.saction= NULL; - G.buts= NULL; - G.v2d= NULL; - G.vd= NULL; - G.soops= NULL; - G.sima= NULL; - G.sipo= NULL; - - free_vertexpaint(); - G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT + G_PARTICLEEDIT); } @@ -292,7 +253,7 @@ static void clean_paths(Main *main) } while(scene) { - ed= scene->ed; + ed= seq_give_editing(scene, 0); if(ed) { seq= ed->seqbasep->first; while(seq) { @@ -314,7 +275,10 @@ static void clean_paths(Main *main) } } -static void setup_app_data(BlendFileData *bfd, char *filename) +/* context matching */ +/* handle no-ui case */ + +static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) { Object *ob; bScreen *curscreen= NULL; @@ -328,16 +292,19 @@ static void setup_app_data(BlendFileData *bfd, char *filename) clean_paths(bfd->main); + /* XXX here the complex windowmanager matching */ + /* no load screens? */ if(mode) { /* comes from readfile.c */ - extern void lib_link_screen_restore(Main *, Scene *); + extern void lib_link_screen_restore(Main *, bScreen *, Scene *); + SWAP(ListBase, G.main->wm, bfd->main->wm); SWAP(ListBase, G.main->screen, bfd->main->screen); SWAP(ListBase, G.main->script, bfd->main->script); /* we re-use current screen */ - curscreen= G.curscreen; + curscreen= CTX_wm_screen(C); /* but use new Scene pointer */ curscene= bfd->curscene; if(curscene==NULL) curscene= bfd->main->scene.first; @@ -345,22 +312,23 @@ static void setup_app_data(BlendFileData *bfd, char *filename) curscreen->scene= curscene; /* clear_global will free G.main, here we can still restore pointers */ - lib_link_screen_restore(bfd->main, curscene); + lib_link_screen_restore(bfd->main, curscreen, curscene); } - clear_global(); /* free Main database */ - - if(mode!='u') G.save_over = 1; + /* free G.main Main database */ + clear_global(); G.main= bfd->main; + + CTX_data_main_set(C, G.main); + if (bfd->user) { /* only here free userdef themes... */ - BLI_freelistN(&U.themes); - + BKE_userdef_free(); + U= *bfd->user; MEM_freeN(bfd->user); - } /* samples is a global list... */ @@ -368,52 +336,61 @@ static void setup_app_data(BlendFileData *bfd, char *filename) /* case G_FILE_NO_UI or no screens in file */ if(mode) { - G.curscreen= curscreen; - G.scene= curscene; + /* leave entire context further unaltered? */ + CTX_data_scene_set(C, curscene); } else { G.winpos= bfd->winpos; G.displaymode= bfd->displaymode; G.fileflags= bfd->fileflags; - G.curscreen= bfd->curscreen; - G.scene= G.curscreen->scene; + + CTX_wm_screen_set(C, bfd->curscreen); + CTX_data_scene_set(C, bfd->curscreen->scene); + CTX_wm_area_set(C, NULL); + CTX_wm_region_set(C, NULL); + CTX_wm_menu_set(C, NULL); } + /* this can happen when active scene was lib-linked, and doesnt exist anymore */ - if(G.scene==NULL) { - G.scene= G.main->scene.first; - G.curscreen->scene= G.scene; + if(CTX_data_scene(C)==NULL) { + CTX_data_scene_set(C, bfd->main->scene.first); + CTX_wm_screen(C)->scene= CTX_data_scene(C); + curscene= CTX_data_scene(C); } /* special cases, override loaded flags: */ if (G.f & G_DEBUG) bfd->globalf |= G_DEBUG; else bfd->globalf &= ~G_DEBUG; + if (G.f & G_SWAP_EXCHANGE) bfd->globalf |= G_SWAP_EXCHANGE; + else bfd->globalf &= ~G_SWAP_EXCHANGE; if ((U.flag & USER_DONT_DOSCRIPTLINKS)) bfd->globalf &= ~G_DOSCRIPTLINKS; G.f= bfd->globalf; if (!G.background) { - setscreen(G.curscreen); + //setscreen(G.curscreen); } + // XXX temporarily here + if(G.main->versionfile < 250) + do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching + /* baseflags, groups, make depsgraph, etc */ - set_scene_bg(G.scene); - - /* clear BONE_UNKEYED flags, these are not valid anymore for proxies */ - framechange_poses_clear_unkeyed(); + set_scene_bg(CTX_data_scene(C)); /* last stage of do_versions actually, that sets recalc flags for recalc poses */ for(ob= G.main->object.first; ob; ob= ob->id.next) { if(ob->type==OB_ARMATURE) - if(ob->recalc) object_handle_update(ob); + if(ob->recalc) object_handle_update(CTX_data_scene(C), ob); } /* now tag update flags, to ensure deformers get calculated on redraw */ - DAG_scene_update_flags(G.scene, G.scene->lay); + DAG_scene_update_flags(CTX_data_scene(C), CTX_data_scene(C)->lay); if (G.f & G_DOSCRIPTLINKS) { /* there's an onload scriptlink to execute in screenmain */ - mainqenter(ONLOAD_SCRIPT, 1); +// XXX mainqenter(ONLOAD_SCRIPT, 1); } if (G.sce != filename) /* these are the same at times, should never copy to the same location */ strcpy(G.sce, filename); @@ -423,7 +400,7 @@ static void setup_app_data(BlendFileData *bfd, char *filename) MEM_freeN(bfd); } -static void handle_subversion_warning(Main *main) +static int handle_subversion_warning(Main *main) { if(main->minversionfile > BLENDER_VERSION || (main->minversionfile == BLENDER_VERSION && @@ -432,9 +409,18 @@ static void handle_subversion_warning(Main *main) char str[128]; sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile); - error(str); +// XXX error(str); } - + return 1; +} + +void BKE_userdef_free(void) +{ + + BLI_freelistN(&U.uistyles); + BLI_freelistN(&U.uifonts); + BLI_freelistN(&U.themes); + } /* returns: @@ -443,79 +429,75 @@ static void handle_subversion_warning(Main *main) 2: OK, and with new user settings */ -int BKE_read_file(char *dir, void *type_r) +int BKE_read_file(bContext *C, char *dir, void *unused, ReportList *reports) { - BlendReadError bre; BlendFileData *bfd; int retval= 1; - - if (!G.background) - waitcursor(1); - - bfd= BLO_read_from_file(dir, &bre); + + bfd= BLO_read_from_file(dir, reports); if (bfd) { if(bfd->user) retval= 2; - if (type_r) - *((BlenFileType*)type_r)= bfd->type; - setup_app_data(bfd, dir); - - handle_subversion_warning(G.main); + if(0==handle_subversion_warning(bfd->main)) { + free_main(bfd->main); + MEM_freeN(bfd); + bfd= NULL; + retval= 0; + } + else + setup_app_data(C, bfd, dir); // frees BFD } - else { - error("Loading %s failed: %s", dir, BLO_bre_as_string(bre)); - } - - if (!G.background) - waitcursor(0); - + else + BKE_reports_prependf(reports, "Loading %s failed: ", dir); + return (bfd?retval:0); } -int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r) +int BKE_read_file_from_memory(bContext *C, char* filebuf, int filelength, void *unused, ReportList *reports) { - BlendReadError bre; BlendFileData *bfd; - - if (!G.background) - waitcursor(1); - - bfd= BLO_read_from_memory(filebuf, filelength, &bre); - if (bfd) { - if (type_r) - *((BlenFileType*)type_r)= bfd->type; - - setup_app_data(bfd, "<memory2>"); - } else { - error("Loading failed: %s", BLO_bre_as_string(bre)); - } - - if (!G.background) - waitcursor(0); - + + bfd= BLO_read_from_memory(filebuf, filelength, reports); + if (bfd) + setup_app_data(C, bfd, "<memory2>"); + else + BKE_reports_prepend(reports, "Loading failed: "); + return (bfd?1:0); } /* memfile is the undo buffer */ -int BKE_read_file_from_memfile(MemFile *memfile) +int BKE_read_file_from_memfile(bContext *C, MemFile *memfile, ReportList *reports) { - BlendReadError bre; BlendFileData *bfd; - - if (!G.background) - waitcursor(1); - - bfd= BLO_read_from_memfile(G.sce, memfile, &bre); - if (bfd) { - setup_app_data(bfd, "<memory1>"); - } else { - error("Loading failed: %s", BLO_bre_as_string(bre)); + + bfd= BLO_read_from_memfile(CTX_data_main(C), G.sce, memfile, reports); + if (bfd) + setup_app_data(C, bfd, "<memory1>"); + else + BKE_reports_prepend(reports, "Loading failed: "); + + return (bfd?1:0); +} + +/* ***************** testing for break ************* */ + +static void (*blender_test_break_cb)(void)= NULL; + +void set_blender_test_break_cb(void (*func)(void) ) +{ + blender_test_break_cb= func; +} + + +int blender_test_break(void) +{ + if (!G.background) { + if (blender_test_break_cb) + blender_test_break_cb(); } - if (!G.background) - waitcursor(0); - - return (bfd?1:0); + return (G.afbreek==1); } @@ -536,7 +518,7 @@ static ListBase undobase={NULL, NULL}; static UndoElem *curundo= NULL; -static int read_undosave(UndoElem *uel) +static int read_undosave(bContext *C, UndoElem *uel) { char scestr[FILE_MAXDIR+FILE_MAXFILE]; int success=0, fileflags; @@ -546,10 +528,10 @@ static int read_undosave(UndoElem *uel) G.fileflags |= G_FILE_NO_UI; if(UNDO_DISK) - success= BKE_read_file(uel->str, NULL); + success= BKE_read_file(C, uel->str, NULL, NULL); else - success= BKE_read_file_from_memfile(&uel->memfile); - + success= BKE_read_file_from_memfile(C, &uel->memfile, NULL); + /* restore */ strcpy(G.sce, scestr); G.fileflags= fileflags; @@ -558,7 +540,7 @@ static int read_undosave(UndoElem *uel) } /* name can be a dynamic string */ -void BKE_write_undo(char *name) +void BKE_write_undo(bContext *C, char *name) { uintptr_t maxmem, totmem, memused; int nr, success; @@ -602,7 +584,7 @@ void BKE_write_undo(char *name) /* disk save version */ if(UNDO_DISK) { static int counter= 0; - char *err, tstr[FILE_MAXDIR+FILE_MAXFILE]; + char tstr[FILE_MAXDIR+FILE_MAXFILE]; char numstr[32]; /* calculate current filename */ @@ -612,18 +594,17 @@ void BKE_write_undo(char *name) sprintf(numstr, "%d.blend", counter); BLI_make_file_string("/", tstr, btempdir, numstr); - success= BLO_write_file(tstr, G.fileflags, &err); + success= BLO_write_file(CTX_data_main(C), tstr, G.fileflags, NULL); strcpy(curundo->str, tstr); } else { MemFile *prevfile=NULL; - char *err; if(curundo->prev) prevfile= &(curundo->prev->memfile); memused= MEM_get_memory_in_use(); - success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err); + success= BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags, NULL); curundo->undosize= MEM_get_memory_in_use() - memused; } @@ -657,28 +638,28 @@ void BKE_write_undo(char *name) /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation * Note, ALWAYS call sound_initialize_sounds after BKE_undo_step() */ -void BKE_undo_step(int step) +void BKE_undo_step(bContext *C, int step) { if(step==0) { - read_undosave(curundo); + read_undosave(C, curundo); } else if(step==1) { /* curundo should never be NULL, after restart or load file it should call undo_save */ - if(curundo==NULL || curundo->prev==NULL) error("No undo available"); + if(curundo==NULL || curundo->prev==NULL) ; // XXX error("No undo available"); else { if(G.f & G_DEBUG) printf("undo %s\n", curundo->name); curundo= curundo->prev; - read_undosave(curundo); + read_undosave(C, curundo); } } else { /* curundo has to remain current situation! */ - if(curundo==NULL || curundo->next==NULL) error("No redo available"); + if(curundo==NULL || curundo->next==NULL) ; // XXX error("No redo available"); else { - read_undosave(curundo->next); + read_undosave(C, curundo->next); curundo= curundo->next; if(G.f & G_DEBUG) printf("redo %s\n", curundo->name); } @@ -700,7 +681,7 @@ void BKE_reset_undo(void) } /* based on index nr it does a restore */ -void BKE_undo_number(int nr) +void BKE_undo_number(bContext *C, int nr) { UndoElem *uel; int a=1; @@ -709,7 +690,7 @@ void BKE_undo_number(int nr) if(a==nr) break; } curundo= uel; - BKE_undo_step(0); + BKE_undo_step(C, 0); } char *BKE_undo_menu_string(void) @@ -754,7 +735,7 @@ void BKE_undo_save_quit(void) file = open(str,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666); if(file == -1) { - error("Unable to save %s, check you have permissions", str); + //XXX error("Unable to save %s, check you have permissions", str); return; } @@ -766,7 +747,7 @@ void BKE_undo_save_quit(void) close(file); - if(chunk) error("Unable to save %s, internal error", str); + if(chunk) ; //XXX error("Unable to save %s, internal error", str); else printf("Saved session recovery to %s\n", str); } diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index 0af54b86ed6..09770b2b4ba 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -178,7 +178,7 @@ void detectBitmapFont(ImBuf *ibuf) { unsigned char * rect; unsigned short version; - long i; + int i; if (ibuf != NULL) { // bitmap must have an x size that is a power of two diff --git a/source/blender/blenkernel/intern/booleanops.c b/source/blender/blenkernel/intern/booleanops.c new file mode 100644 index 00000000000..27b78c6644c --- /dev/null +++ b/source/blender/blenkernel/intern/booleanops.c @@ -0,0 +1,576 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * CSG operations. + */ + +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_ghash.h" + +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "CSG_BooleanOps.h" + +#include "BKE_booleanops.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + + + +/** + * Here's the vertex iterator structure used to walk through + * the blender vertex structure. + */ + +typedef struct { + DerivedMesh *dm; + Object *ob; + int pos; +} VertexIt; + +/** + * Implementations of local vertex iterator functions. + * These describe a blender mesh to the CSG module. + */ + +static void VertexIt_Destruct(CSG_VertexIteratorDescriptor * iterator) +{ + if (iterator->it) { + // deallocate memory for iterator + MEM_freeN(iterator->it); + iterator->it = 0; + } + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; + +} + +static int VertexIt_Done(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + return(iterator->pos >= iterator->dm->getNumVerts(iterator->dm)); +} + +static void VertexIt_Fill(CSG_IteratorPtr it, CSG_IVertex *vert) +{ + VertexIt * iterator = (VertexIt *)it; + MVert *verts = iterator->dm->getVertArray(iterator->dm); + + float global_pos[3]; + + /* boolean happens in global space, transform both with obmat */ + VecMat4MulVecfl( + global_pos, + iterator->ob->obmat, + verts[iterator->pos].co + ); + + vert->position[0] = global_pos[0]; + vert->position[1] = global_pos[1]; + vert->position[2] = global_pos[2]; +} + +static void VertexIt_Step(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + iterator->pos ++; +} + +static void VertexIt_Reset(CSG_IteratorPtr it) +{ + VertexIt * iterator = (VertexIt *)it; + iterator->pos = 0; +} + +static void VertexIt_Construct(CSG_VertexIteratorDescriptor *output, DerivedMesh *dm, Object *ob) +{ + + VertexIt *it; + if (output == 0) return; + + // allocate some memory for blender iterator + it = (VertexIt *)(MEM_mallocN(sizeof(VertexIt),"Boolean_VIt")); + if (it == 0) { + return; + } + // assign blender specific variables + it->dm = dm; + it->ob = ob; // needed for obmat transformations + + it->pos = 0; + + // assign iterator function pointers. + output->Step = VertexIt_Step; + output->Fill = VertexIt_Fill; + output->Done = VertexIt_Done; + output->Reset = VertexIt_Reset; + output->num_elements = it->dm->getNumVerts(it->dm); + output->it = it; +} + +/** + * Blender Face iterator + */ + +typedef struct { + DerivedMesh *dm; + int pos; + int offset; +} FaceIt; + +static void FaceIt_Destruct(CSG_FaceIteratorDescriptor * iterator) +{ + MEM_freeN(iterator->it); + iterator->Done = NULL; + iterator->Fill = NULL; + iterator->Reset = NULL; + iterator->Step = NULL; + iterator->num_elements = 0; +} + +static int FaceIt_Done(CSG_IteratorPtr it) +{ + // assume CSG_IteratorPtr is of the correct type. + FaceIt * iterator = (FaceIt *)it; + return(iterator->pos >= iterator->dm->getNumFaces(iterator->dm)); +} + +static void FaceIt_Fill(CSG_IteratorPtr it, CSG_IFace *face) +{ + // assume CSG_IteratorPtr is of the correct type. + FaceIt *face_it = (FaceIt *)it; + MFace *mfaces = face_it->dm->getFaceArray(face_it->dm); + MFace *mface = &mfaces[face_it->pos]; + + face->vertex_index[0] = mface->v1; + face->vertex_index[1] = mface->v2; + face->vertex_index[2] = mface->v3; + if (mface->v4) { + face->vertex_index[3] = mface->v4; + face->vertex_number = 4; + } else { + face->vertex_number = 3; + } + + face->orig_face = face_it->offset + face_it->pos; +} + +static void FaceIt_Step(CSG_IteratorPtr it) +{ + FaceIt * face_it = (FaceIt *)it; + face_it->pos ++; +} + +static void FaceIt_Reset(CSG_IteratorPtr it) +{ + FaceIt * face_it = (FaceIt *)it; + face_it->pos = 0; +} + +static void FaceIt_Construct( + CSG_FaceIteratorDescriptor *output, DerivedMesh *dm, int offset) +{ + FaceIt *it; + if (output == 0) return; + + // allocate some memory for blender iterator + it = (FaceIt *)(MEM_mallocN(sizeof(FaceIt),"Boolean_FIt")); + if (it == 0) { + return ; + } + // assign blender specific variables + it->dm = dm; + it->offset = offset; + it->pos = 0; + + // assign iterator function pointers. + output->Step = FaceIt_Step; + output->Fill = FaceIt_Fill; + output->Done = FaceIt_Done; + output->Reset = FaceIt_Reset; + output->num_elements = it->dm->getNumFaces(it->dm); + output->it = it; +} + +static Object *AddNewBlenderMesh(Scene *scene, Base *base) +{ + // This little function adds a new mesh object to the blender object list + // It uses ob to duplicate data as this seems to be easier than creating + // a new one. This new oject contains no faces nor vertices. + Mesh *old_me; + Base *basen; + Object *ob_new; + + // now create a new blender object. + // duplicating all the settings from the previous object + // to the new one. + ob_new= copy_object(base->object); + + // Ok we don't want to use the actual data from the + // last object, the above function incremented the + // number of users, so decrement it here. + old_me= ob_new->data; + old_me->id.us--; + + // Now create a new base to add into the linked list of + // vase objects. + + basen= MEM_mallocN(sizeof(Base), "duplibase"); + *basen= *base; + BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */ + basen->object= ob_new; + basen->flag &= ~SELECT; + + // Initialize the mesh data associated with this object. + ob_new->data= add_mesh("Mesh"); + + // Finally assign the object type. + ob_new->type= OB_MESH; + + return ob_new; +} + +static void InterpCSGFace( + DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr, + float mapmat[][4]) +{ + float obco[3], *co[4], *orig_co[4], w[4][4]; + MFace *mface, *orig_mface; + int j; + + mface = CDDM_get_face(dm, index); + orig_mface = orig_dm->getFaceArray(orig_dm) + orig_index; + + // get the vertex coordinates from the original mesh + orig_co[0] = (orig_dm->getVertArray(orig_dm) + orig_mface->v1)->co; + orig_co[1] = (orig_dm->getVertArray(orig_dm) + orig_mface->v2)->co; + orig_co[2] = (orig_dm->getVertArray(orig_dm) + orig_mface->v3)->co; + orig_co[3] = (orig_mface->v4)? (orig_dm->getVertArray(orig_dm) + orig_mface->v4)->co: NULL; + + // get the vertex coordinates from the new derivedmesh + co[0] = CDDM_get_vert(dm, mface->v1)->co; + co[1] = CDDM_get_vert(dm, mface->v2)->co; + co[2] = CDDM_get_vert(dm, mface->v3)->co; + co[3] = (nr == 4)? CDDM_get_vert(dm, mface->v4)->co: NULL; + + for (j = 0; j < nr; j++) { + // get coordinate into the space of the original mesh + if (mapmat) + VecMat4MulVecfl(obco, mapmat, co[j]); + else + VecCopyf(obco, co[j]); + + InterpWeightsQ3Dfl(orig_co[0], orig_co[1], orig_co[2], orig_co[3], obco, w[j]); + } + + CustomData_interp(&orig_dm->faceData, &dm->faceData, &orig_index, NULL, (float*)w, 1, index); +} + +/* Iterate over the CSG Output Descriptors and create a new DerivedMesh + from them */ +static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh( + CSG_FaceIteratorDescriptor *face_it, + CSG_VertexIteratorDescriptor *vertex_it, + float parinv[][4], + float mapmat[][4], + Material **mat, + int *totmat, + DerivedMesh *dm1, + Object *ob1, + DerivedMesh *dm2, + Object *ob2) +{ + DerivedMesh *result, *orig_dm; + GHash *material_hash = NULL; + Mesh *me1= (Mesh*)ob1->data; + Mesh *me2= (Mesh*)ob2->data; + int i; + + // create a new DerivedMesh + result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements); + CustomData_merge(&dm1->faceData, &result->faceData, CD_MASK_DERIVEDMESH, + CD_DEFAULT, face_it->num_elements); + CustomData_merge(&dm2->faceData, &result->faceData, CD_MASK_DERIVEDMESH, + CD_DEFAULT, face_it->num_elements); + + // step through the vertex iterators: + for (i = 0; !vertex_it->Done(vertex_it->it); i++) { + CSG_IVertex csgvert; + MVert *mvert = CDDM_get_vert(result, i); + + // retrieve a csg vertex from the boolean module + vertex_it->Fill(vertex_it->it, &csgvert); + vertex_it->Step(vertex_it->it); + + // we have to map the vertex coordinates back in the coordinate frame + // of the resulting object, since it was computed in world space + VecMat4MulVecfl(mvert->co, parinv, csgvert.position); + } + + // a hash table to remap materials to indices + if (mat) { + material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + *totmat = 0; + } + + // step through the face iterators + for(i = 0; !face_it->Done(face_it->it); i++) { + Mesh *orig_me; + Object *orig_ob; + Material *orig_mat; + CSG_IFace csgface; + MFace *mface; + int orig_index, mat_nr; + + // retrieve a csg face from the boolean module + face_it->Fill(face_it->it, &csgface); + face_it->Step(face_it->it); + + // find the original mesh and data + orig_ob = (csgface.orig_face < dm1->getNumFaces(dm1))? ob1: ob2; + orig_dm = (csgface.orig_face < dm1->getNumFaces(dm1))? dm1: dm2; + orig_me = (orig_ob == ob1)? me1: me2; + orig_index = (orig_ob == ob1)? csgface.orig_face: csgface.orig_face - dm1->getNumFaces(dm1); + + // copy all face layers, including mface + CustomData_copy_data(&orig_dm->faceData, &result->faceData, orig_index, i, 1); + + // set mface + mface = CDDM_get_face(result, i); + mface->v1 = csgface.vertex_index[0]; + mface->v2 = csgface.vertex_index[1]; + mface->v3 = csgface.vertex_index[2]; + mface->v4 = (csgface.vertex_number == 4)? csgface.vertex_index[3]: 0; + + // set material, based on lookup in hash table + orig_mat= give_current_material(orig_ob, mface->mat_nr+1); + + if (mat && orig_mat) { + if (!BLI_ghash_haskey(material_hash, orig_mat)) { + mat[*totmat] = orig_mat; + mat_nr = mface->mat_nr = (*totmat)++; + BLI_ghash_insert(material_hash, orig_mat, SET_INT_IN_POINTER(mat_nr)); + } + else + mface->mat_nr = GET_INT_FROM_POINTER(BLI_ghash_lookup(material_hash, orig_mat)); + } + else + mface->mat_nr = 0; + + InterpCSGFace(result, orig_dm, i, orig_index, csgface.vertex_number, + (orig_me == me2)? mapmat: NULL); + + test_index_face(mface, &result->faceData, i, csgface.vertex_number); + } + + if (material_hash) + BLI_ghash_free(material_hash, NULL, NULL); + + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + return result; +} + +static void BuildMeshDescriptors( + struct DerivedMesh *dm, + struct Object *ob, + int face_offset, + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it) +{ + VertexIt_Construct(vertex_it,dm, ob); + FaceIt_Construct(face_it,dm,face_offset); +} + +static void FreeMeshDescriptors( + struct CSG_FaceIteratorDescriptor *face_it, + struct CSG_VertexIteratorDescriptor *vertex_it) +{ + VertexIt_Destruct(vertex_it); + FaceIt_Destruct(face_it); +} + +DerivedMesh *NewBooleanDerivedMesh_intern( + DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, + int int_op_type, Material **mat, int *totmat) +{ + + float inv_mat[4][4]; + float map_mat[4][4]; + + DerivedMesh *result = NULL; + + if (dm == NULL || dm_select == NULL) return 0; + if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) return 0; + + // we map the final object back into ob's local coordinate space. For this + // we need to compute the inverse transform from global to ob (inv_mat), + // and the transform from ob to ob_select for use in interpolation (map_mat) + Mat4Invert(inv_mat, ob->obmat); + Mat4MulMat4(map_mat, ob_select->obmat, inv_mat); + Mat4Invert(inv_mat, ob_select->obmat); + + { + // interface with the boolean module: + // + // the idea is, we pass the boolean module verts and faces using the + // provided descriptors. once the boolean operation is performed, we + // get back output descriptors, from which we then build a DerivedMesh + + CSG_VertexIteratorDescriptor vd_1, vd_2; + CSG_FaceIteratorDescriptor fd_1, fd_2; + CSG_OperationType op_type; + CSG_BooleanOperation *bool_op; + + // work out the operation they chose and pick the appropriate + // enum from the csg module. + switch (int_op_type) { + case 1 : op_type = e_csg_intersection; break; + case 2 : op_type = e_csg_union; break; + case 3 : op_type = e_csg_difference; break; + case 4 : op_type = e_csg_classify; break; + default : op_type = e_csg_intersection; + } + + BuildMeshDescriptors(dm_select, ob_select, 0, &fd_1, &vd_1); + BuildMeshDescriptors(dm, ob, dm_select->getNumFaces(dm_select) , &fd_2, &vd_2); + + bool_op = CSG_NewBooleanFunction(); + + // perform the operation + if (CSG_PerformBooleanOperation(bool_op, op_type, fd_1, vd_1, fd_2, vd_2)) { + CSG_VertexIteratorDescriptor vd_o; + CSG_FaceIteratorDescriptor fd_o; + + CSG_OutputFaceDescriptor(bool_op, &fd_o); + CSG_OutputVertexDescriptor(bool_op, &vd_o); + + // iterate through results of operation and insert + // into new object + result = ConvertCSGDescriptorsToDerivedMesh( + &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob); + + // free up the memory + CSG_FreeVertexDescriptor(&vd_o); + CSG_FreeFaceDescriptor(&fd_o); + } +// else +// XXX error("Unknown internal error in boolean"); + + CSG_FreeBooleanOperation(bool_op); + + FreeMeshDescriptors(&fd_1, &vd_1); + FreeMeshDescriptors(&fd_2, &vd_2); + } + + return result; +} + +int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) +{ + Mesh *me_new; + int a, maxmat, totmat= 0; + Object *ob_new, *ob, *ob_select; + Material **mat; + DerivedMesh *result; + DerivedMesh *dm_select; + DerivedMesh *dm; + + ob= base->object; + ob_select= base_select->object; + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ?? + + maxmat= ob->totcol + ob_select->totcol; + mat= (Material**)MEM_mallocN(sizeof(Material*)*maxmat, "NewBooleanMeshMat"); + + /* put some checks in for nice user feedback */ + if (dm == NULL || dm_select == NULL) return 0; + if (!dm->getNumFaces(dm) || !dm_select->getNumFaces(dm_select)) + { + MEM_freeN(mat); + return -1; + } + + result= NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat); + + if (result == NULL) { + MEM_freeN(mat); + return 0; + } + + /* create a new blender mesh object - using 'base' as a template */ + ob_new= AddNewBlenderMesh(scene, base_select); + me_new= ob_new->data; + + DM_to_mesh(result, me_new); + result->release(result); + + dm->release(dm); + dm_select->release(dm_select); + + /* add materials to object */ + for (a = 0; a < totmat; a++) + assign_material(ob_new, mat[a], a+1); + + MEM_freeN(mat); + + /* update dag */ + DAG_object_flush_update(scene, ob_new, OB_RECALC_DATA); + + return 1; +} + +DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, + int int_op_type) +{ + return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL); +} + diff --git a/source/blender/blenkernel/intern/booleanops_mesh.c b/source/blender/blenkernel/intern/booleanops_mesh.c new file mode 100644 index 00000000000..14e32873dbd --- /dev/null +++ b/source/blender/blenkernel/intern/booleanops_mesh.c @@ -0,0 +1,293 @@ +#if 0 + +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include "CSG_BooleanOps.h" + +#include "BKE_booleanops.h" +#include "BKE_booleanops_mesh.h" +#include "MEM_guardedalloc.h" + +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_displist.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_library.h" +#include "BKE_material.h" + +#include "BLI_arithb.h" + +/** + * Implementation of boolean ops mesh interface. + */ + + void +CSG_DestroyMeshDescriptor( + CSG_MeshDescriptor *mesh +){ + // Call mesh descriptors destroy function.... + mesh->m_destroy_func(mesh); +} + +// Destroy function for blender mesh internals. + +static + void +CSG_DestroyBlenderMeshInternals( + CSG_MeshDescriptor *mesh +) { + // Free face and vertex iterators. + FreeMeshDescriptors(&(mesh->m_face_iterator),&(mesh->m_vertex_iterator)); +} + + +static + void +CSG_DestroyCSGMeshInternals( + CSG_MeshDescriptor *mesh +){ + CSG_FreeVertexDescriptor(&(mesh->m_vertex_iterator)); + CSG_FreeFaceDescriptor(&(mesh->m_face_iterator)); +} + +static + int +MakeCSGMeshFromBlenderBase( + Base * base, + CSG_MeshDescriptor * output +) { + Mesh *me; + if (output == NULL || base == NULL) return 0; + + me = get_mesh(base->object); + + output->m_descriptor.user_face_vertex_data_size = 0; + output->m_descriptor.user_data_size = sizeof(FaceData); + + output->base = base; + + BuildMeshDescriptors( + base->object, + &(output->m_face_iterator), + &(output->m_vertex_iterator) + ); + + output->m_destroy_func = CSG_DestroyBlenderMeshInternals; + + return 1; +} + + int +CSG_LoadBlenderMesh( + Object * obj, + CSG_MeshDescriptor *output +){ + + Mesh *me; + if (output == NULL || obj == NULL) return 0; + + me = get_mesh(obj); + + output->m_descriptor.user_face_vertex_data_size = 0; + output->m_descriptor.user_data_size = sizeof(FaceData); + + output->base = NULL; + + BuildMeshDescriptors( + obj, + &(output->m_face_iterator), + &(output->m_vertex_iterator) + ); + + output->m_destroy_func = CSG_DestroyBlenderMeshInternals; + output->base = NULL; + + return 1; +} + + + + + int +CSG_AddMeshToBlender( + CSG_MeshDescriptor *mesh +){ + Mesh *me_new = NULL; + Object *ob_new = NULL; + float inv_mat[4][4]; + + if (mesh == NULL) return 0; + if (mesh->base == NULL) return 0; + + Mat4Invert(inv_mat,mesh->base->object->obmat); + + // Create a new blender mesh object - using 'base' as + // a template for the new object. + ob_new= AddNewBlenderMesh(mesh->base); + + me_new = ob_new->data; + + // make sure the iterators are reset. + mesh->m_face_iterator.Reset(mesh->m_face_iterator.it); + mesh->m_vertex_iterator.Reset(mesh->m_vertex_iterator.it); + + // iterate through results of operation and insert into new object + // see subsurf.c + + ConvertCSGDescriptorsToMeshObject( + ob_new, + &(mesh->m_descriptor), + &(mesh->m_face_iterator), + &(mesh->m_vertex_iterator), + inv_mat + ); + + return 1; +} + + int +CSG_PerformOp( + CSG_MeshDescriptor *mesh1, + CSG_MeshDescriptor *mesh2, + int int_op_type, + CSG_MeshDescriptor *output +){ + + CSG_OperationType op_type; + CSG_BooleanOperation * bool_op = CSG_NewBooleanFunction(); + int success = 0; + + if (bool_op == NULL) return 0; + + if ((mesh1 == NULL) || (mesh2 == NULL) || (output == NULL)) { + return 0; + } + if ((int_op_type < 1) || (int_op_type > 3)) return 0; + + switch (int_op_type) { + case 1 : op_type = e_csg_intersection; break; + case 2 : op_type = e_csg_union; break; + case 3 : op_type = e_csg_difference; break; + case 4 : op_type = e_csg_classify; break; + default : op_type = e_csg_intersection; + } + + output->m_descriptor = CSG_DescibeOperands(bool_op,mesh1->m_descriptor,mesh2->m_descriptor); + output->base = mesh1->base; + + if (output->m_descriptor.user_face_vertex_data_size) { + // Then use the only interp function supported + success = + CSG_PerformBooleanOperation( + bool_op, + op_type, + mesh1->m_face_iterator, + mesh1->m_vertex_iterator, + mesh2->m_face_iterator, + mesh2->m_vertex_iterator, + InterpFaceVertexData + ); + } else { + success = + CSG_PerformBooleanOperation( + bool_op, + op_type, + mesh1->m_face_iterator, + mesh1->m_vertex_iterator, + mesh2->m_face_iterator, + mesh2->m_vertex_iterator, + InterpNoUserData + ); + } + + if (!success) { + CSG_FreeBooleanOperation(bool_op); + bool_op = NULL; + return 0; + } + + // get the ouput mesh descriptors. + + CSG_OutputFaceDescriptor(bool_op,&(output->m_face_iterator)); + CSG_OutputVertexDescriptor(bool_op,&(output->m_vertex_iterator)); + output->m_destroy_func = CSG_DestroyCSGMeshInternals; + + return 1; +} + + int +NewBooleanMeshTest( + struct Base * base, + struct Base * base_select, + int op_type +){ + + CSG_MeshDescriptor m1,m2,output; + CSG_MeshDescriptor output2,output3; + + if (!MakeCSGMeshFromBlenderBase(base,&m1)) { + return 0; + } + + if (!MakeCSGMeshFromBlenderBase(base_select,&m2)) { + return 0; + } + + CSG_PerformOp(&m1,&m2,1,&output); + CSG_PerformOp(&m1,&m2,2,&output2); + CSG_PerformOp(&m1,&m2,3,&output3); + + if (!CSG_AddMeshToBlender(&output)) { + return 0; + } + if (!CSG_AddMeshToBlender(&output2)) { + return 0; + } + if (!CSG_AddMeshToBlender(&output3)) { + return 0; + } + + + CSG_DestroyMeshDescriptor(&m1); + CSG_DestroyMeshDescriptor(&m2); + CSG_DestroyMeshDescriptor(&output); + CSG_DestroyMeshDescriptor(&output2); + CSG_DestroyMeshDescriptor(&output3); + + return 1; +} + +#endif + diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 021f76fd2f1..30a35cbe91c 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -28,19 +28,26 @@ */ #include <math.h> +#include <string.h> #include "MEM_guardedalloc.h" #include "DNA_brush_types.h" +#include "DNA_color_types.h" #include "DNA_image_types.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_access.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_texture.h" @@ -50,6 +57,7 @@ #include "IMB_imbuf_types.h" #include "RE_render_ext.h" /* externtex */ +#include "RE_shader_ext.h" /* Datablock add/copy/free/make_local */ @@ -68,6 +76,9 @@ Brush *add_brush(char *name) brush->rate= 0.1f; brush->innerradius= 0.5f; brush->clone.alpha= 0.5; + brush->sculpt_tool = SCULPT_TOOL_DRAW; + + brush_curve_preset(brush, BRUSH_PRESET_SHARP); /* enable fake user by default */ brush->id.flag |= LIB_FAKEUSER; @@ -92,6 +103,8 @@ Brush *copy_brush(Brush *brush) } } + brushn->curve= curvemapping_copy(brush->curve); + /* enable fake user by default */ if (!(brushn->id.flag & LIB_FAKEUSER)) { brushn->id.flag |= LIB_FAKEUSER; @@ -114,6 +127,8 @@ void free_brush(Brush *brush) MEM_freeN(mtex); } } + + curvemapping_free(brush->curve); } void make_local_brush(Brush *brush) @@ -170,6 +185,19 @@ void make_local_brush(Brush *brush) /* Library Operations */ +Brush **current_brush_source(Scene *sce) +{ + if(G.f & G_SCULPTMODE) + return &sce->toolsettings->sculpt->brush; + else if(G.f & G_VERTEXPAINT) + return &sce->toolsettings->vpaint->brush; + else if(G.f & G_WEIGHTPAINT) + return &sce->toolsettings->wpaint->brush; + else if(G.f & G_TEXTUREPAINT) + return &sce->toolsettings->imapaint.brush; + return NULL; +} + int brush_set_nr(Brush **current_brush, int nr) { ID *idtest, *id; @@ -217,6 +245,61 @@ void brush_toggled_fake_user(Brush *brush) } } +void brush_curve_preset(Brush *b, BrushCurvePreset preset) +{ + CurveMap *cm = NULL; + + if(!b->curve) + b->curve = curvemapping_add(1, 0, 0, 1, 1); + + cm = b->curve->cm; + + if(cm->curve) + MEM_freeN(cm->curve); + + if(preset == BRUSH_PRESET_SHARP) + cm->totpoint= 3; + if(preset == BRUSH_PRESET_SMOOTH) + cm->totpoint= 6; + if(preset == BRUSH_PRESET_MAX) + cm->totpoint= 2; + + + cm->curve= MEM_callocN(cm->totpoint*sizeof(CurveMapPoint), "curve points"); + cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + + if(preset == BRUSH_PRESET_SHARP) { + cm->curve[0].x= 0; + cm->curve[0].y= 1; + cm->curve[1].x= 0.33; + cm->curve[1].y= 0.33; + cm->curve[2].x= 1; + cm->curve[2].y= 0; + } + else if(preset == BRUSH_PRESET_SMOOTH) { + cm->curve[0].x= 0; + cm->curve[0].y= 1; + cm->curve[1].x= 0.1; + cm->curve[1].y= 0.97553; + cm->curve[2].x= 0.3; + cm->curve[2].y= 0.79389; + cm->curve[3].x= 0.9; + cm->curve[3].y= 0.02447; + cm->curve[4].x= 0.7; + cm->curve[4].y= 0.20611; + cm->curve[5].x= 1; + cm->curve[5].y= 0; + } + else if(preset == BRUSH_PRESET_MAX) { + cm->curve[0].x= 0; + cm->curve[0].y= 1; + cm->curve[1].x= 1; + cm->curve[1].y= 1; + } + + curvemapping_changed(b->curve, 0); +} + int brush_texture_set_nr(Brush *brush, int nr) { ID *idtest, *id=NULL; @@ -895,4 +978,124 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl return totpaintops; } +/* Uses the brush curve control to find a strength value between 0 and 1 */ +float brush_curve_strength(Brush *br, float p, const float len) +{ + if(p > len) p= len; + return curvemapping_evaluateF(br->curve, 0, p/len); +} + +/* TODO: should probably be unified with BrushPainter stuff? */ +unsigned int *brush_gen_texture_cache(Brush *br, int half_side) +{ + unsigned int *texcache = NULL; + MTex *mtex = br->mtex[br->texact]; + TexResult texres; + int hasrgb, ix, iy; + int side = half_side * 2; + memset(&texres, 0, sizeof(TexResult)); + + if(mtex && mtex->tex) { + float x, y, step = 2.0 / side, co[3]; + + texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); + + BKE_image_get_ibuf(mtex->tex->ima, NULL); + + /*do normalized cannonical view coords for texture*/ + for (y=-1.0, iy=0; iy<side; iy++, y += step) { + for (x=-1.0, ix=0; ix<side; ix++, x += step) { + co[0]= x; + co[1]= y; + co[2]= 0.0f; + + /* This is copied from displace modifier code */ + hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 1, &texres); + + /* if the texture gave an RGB value, we assume it didn't give a valid + * intensity, so calculate one (formula from do_material_tex). + * if the texture didn't give an RGB value, copy the intensity across + */ + if(hasrgb & TEX_RGB) + texres.tin = (0.35 * texres.tr + 0.45 * + texres.tg + 0.2 * texres.tb); + + texres.tin = texres.tin * 255.0; + ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin; + ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin; + ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin; + ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin; + } + } + } + + return texcache; +} + +/**** Radial Control ****/ +static struct ImBuf *brush_gen_radial_control_imbuf(Brush *br) +{ + ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture"); + unsigned int *texcache; + int side = 128; + int half = side / 2; + int i, j; + + texcache = brush_gen_texture_cache(br, half); + im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect"); + im->x = im->y = side; + + for(i=0; i<side; ++i) { + for(j=0; j<side; ++j) { + float magn= sqrt(pow(i - half, 2) + pow(j - half, 2)); + im->rect_float[i*side + j]= brush_curve_strength(br, magn, half); + } + } + + /* Modulate curve with texture */ + if(texcache) { + for(i=0; i<side; ++i) { + for(j=0; j<side; ++j) { + const int col= texcache[i*side+j]; + im->rect_float[i*side+j]*= (((char*)&col)[0]+((char*)&col)[1]+((char*)&col)[2])/3.0f/255.0f; + } + } + + MEM_freeN(texcache); + } + + return im; +} + +void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight) +{ + int mode = RNA_int_get(op->ptr, "mode"); + float original_value= 0; + + if(mode == WM_RADIALCONTROL_SIZE) + original_value = br->size * size_weight; + else if(mode == WM_RADIALCONTROL_STRENGTH) + original_value = br->alpha; + else if(mode == WM_RADIALCONTROL_ANGLE) + original_value = br->rot; + + RNA_float_set(op->ptr, "initial_value", original_value); + op->customdata = brush_gen_radial_control_imbuf(br); +} + +int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight) +{ + int mode = RNA_int_get(op->ptr, "mode"); + float new_value = RNA_float_get(op->ptr, "new_value"); + const float conv = 0.017453293; + + if(mode == WM_RADIALCONTROL_SIZE) + br->size = new_value * size_weight; + else if(mode == WM_RADIALCONTROL_STRENGTH) + br->alpha = new_value; + else if(mode == WM_RADIALCONTROL_ANGLE) + br->rot = new_value * conv; + + return OPERATOR_FINISHED; +} diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c index b389f8c0536..44e8ed1f08c 100644 --- a/source/blender/blenkernel/intern/bullet.c +++ b/source/blender/blenkernel/intern/bullet.c @@ -82,6 +82,7 @@ BulletSoftBody *bsbNew(void) bsb->collisionflags = 0; //bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS; bsb->numclusteriterations = 64; + bsb->welding = 0.f; return bsb; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 2c1b5ced614..57ef920f75b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -42,6 +42,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_multires.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" @@ -52,6 +53,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_fluidsim.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -64,6 +66,7 @@ #include <string.h> #include <limits.h> +#include <math.h> typedef struct { DerivedMesh dm; @@ -479,10 +482,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mv = cddm->mvert; MFace *mf = cddm->mface; - MCol *mc = DM_get_face_data_layer(dm, CD_MCOL); + MCol *mc; float *nors= dm->getFaceDataArray(dm, CD_NORMAL); int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX); + mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL); + if(!mc) + mc = DM_get_face_data_layer(dm, CD_MCOL); + for(i = 0; i < dm->numFaceData; i++, mf++) { int drawSmooth = (mf->flag & ME_SMOOTH); @@ -885,6 +892,7 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) { CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm"); DerivedMesh *dm = &cddm->dm; + CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); int i, *index, alloctype; /* this does a referenced copy, the only new layers being ORIGINDEX, @@ -900,11 +908,11 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) alloctype= CD_REFERENCE; - CustomData_merge(&mesh->vdata, &dm->vertData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype, mesh->totvert); - CustomData_merge(&mesh->edata, &dm->edgeData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, mesh->totedge); - CustomData_merge(&mesh->fdata, &dm->faceData, CD_MASK_MESH, alloctype, + CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype, mesh->totface); cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); @@ -922,12 +930,6 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob) index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX); for(i = 0; i < mesh->totface; ++i, ++index) *index = i; - - /* works in conjunction with hack during modifier calc, where active mcol - layer with weight paint colors is temporarily added */ - if ((G.f & G_WEIGHTPAINT) && - (ob && ob==(G.scene->basact?G.scene->basact->object:NULL))) - CustomData_duplicate_referenced_layer(&dm->faceData, CD_MCOL); return dm; } @@ -1281,3 +1283,192 @@ MFace *CDDM_get_faces(DerivedMesh *dm) return ((CDDerivedMesh*)dm)->mface; } +/* Multires DerivedMesh, extends CDDM */ +typedef struct MultiresDM { + CDDerivedMesh cddm; + + MultiresModifierData *mmd; + + int lvl, totlvl; + float (*orco)[3]; + MVert *subco; + + ListBase *vert_face_map, *vert_edge_map; + IndexNode *vert_face_map_mem, *vert_edge_map_mem; + int *face_offsets; + + Mesh *me; + int modified; + + void (*update)(DerivedMesh*); +} MultiresDM; + +static void MultiresDM_release(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + int mvert_layer; + + /* Before freeing, need to update the displacement map */ + if(dm->needsFree && mrdm->modified) + mrdm->update(dm); + + /* If the MVert data is being used as the sculpt undo store, don't free it */ + mvert_layer = CustomData_get_layer_index(&dm->vertData, CD_MVERT); + if(mvert_layer != -1) { + CustomDataLayer *cd = &dm->vertData.layers[mvert_layer]; + if(cd->data == mrdm->mmd->undo_verts) + cd->flag |= CD_FLAG_NOFREE; + } + + if(DM_release(dm)) { + MEM_freeN(mrdm->subco); + MEM_freeN(mrdm->orco); + if(mrdm->vert_face_map) + MEM_freeN(mrdm->vert_face_map); + if(mrdm->vert_face_map_mem) + MEM_freeN(mrdm->vert_face_map_mem); + if(mrdm->vert_edge_map) + MEM_freeN(mrdm->vert_edge_map); + if(mrdm->vert_edge_map_mem) + MEM_freeN(mrdm->vert_edge_map_mem); + if(mrdm->face_offsets) + MEM_freeN(mrdm->face_offsets); + MEM_freeN(mrdm); + } +} + +DerivedMesh *MultiresDM_new(MultiresSubsurf *ms, DerivedMesh *orig, int numVerts, int numEdges, int numFaces) +{ + MultiresDM *mrdm = MEM_callocN(sizeof(MultiresDM), "MultiresDM"); + CDDerivedMesh *cddm = cdDM_create("MultiresDM CDDM"); + DerivedMesh *dm = NULL; + + mrdm->cddm = *cddm; + MEM_freeN(cddm); + dm = &mrdm->cddm.dm; + + mrdm->mmd = ms->mmd; + mrdm->me = ms->me; + + if(dm) { + MDisps *disps; + MVert *mvert; + int i; + + DM_from_template(dm, orig, numVerts, numEdges, numFaces); + CustomData_free_layers(&dm->faceData, CD_MDISPS, numFaces); + + disps = CustomData_get_layer(&orig->faceData, CD_MDISPS); + if(disps) + CustomData_add_layer(&dm->faceData, CD_MDISPS, CD_REFERENCE, disps, numFaces); + + + mvert = CustomData_get_layer(&orig->vertData, CD_MVERT); + mrdm->orco = MEM_callocN(sizeof(float) * 3 * orig->getNumVerts(orig), "multires orco"); + for(i = 0; i < orig->getNumVerts(orig); ++i) + VecCopyf(mrdm->orco[i], mvert[i].co); + } + else + DM_init(dm, numVerts, numEdges, numFaces); + + CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts); + CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces); + + mrdm->cddm.mvert = CustomData_get_layer(&dm->vertData, CD_MVERT); + mrdm->cddm.medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); + mrdm->cddm.mface = CustomData_get_layer(&dm->faceData, CD_MFACE); + + mrdm->lvl = ms->mmd->lvl; + mrdm->totlvl = ms->mmd->totlvl; + mrdm->subco = MEM_callocN(sizeof(MVert)*numVerts, "multires subdivided verts"); + mrdm->modified = 0; + + dm->release = MultiresDM_release; + + return dm; +} + +Mesh *MultiresDM_get_mesh(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->me; +} + +void *MultiresDM_get_orco(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->orco; + +} + +MVert *MultiresDM_get_subco(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->subco; +} + +int MultiresDM_get_totlvl(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->totlvl; +} + +int MultiresDM_get_lvl(DerivedMesh *dm) +{ + return ((MultiresDM*)dm)->lvl; +} + +void MultiresDM_set_orco(DerivedMesh *dm, float (*orco)[3]) +{ + ((MultiresDM*)dm)->orco = orco; +} + +void MultiresDM_set_update(DerivedMesh *dm, void (*update)(DerivedMesh*)) +{ + ((MultiresDM*)dm)->update = update; +} + +ListBase *MultiresDM_get_vert_face_map(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + + if(!mrdm->vert_face_map) + create_vert_face_map(&mrdm->vert_face_map, &mrdm->vert_face_map_mem, mrdm->me->mface, + mrdm->me->totvert, mrdm->me->totface); + + return mrdm->vert_face_map; +} + +ListBase *MultiresDM_get_vert_edge_map(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + + if(!mrdm->vert_edge_map) + create_vert_edge_map(&mrdm->vert_edge_map, &mrdm->vert_edge_map_mem, mrdm->me->medge, + mrdm->me->totvert, mrdm->me->totedge); + + return mrdm->vert_edge_map; +} + +int *MultiresDM_get_face_offsets(DerivedMesh *dm) +{ + MultiresDM *mrdm = (MultiresDM*)dm; + int i, accum = 0; + + if(!mrdm->face_offsets) { + int len = (int)pow(2, mrdm->lvl - 2) - 1; + int area = len * len; + int t = 1 + len * 3 + area * 3, q = t + len + area; + + mrdm->face_offsets = MEM_callocN(sizeof(int) * mrdm->me->totface, "mrdm face offsets"); + for(i = 0; i < mrdm->me->totface; ++i) { + mrdm->face_offsets[i] = accum; + + accum += (mrdm->me->mface[i].v4 ? q : t); + } + } + + return mrdm->face_offsets; +} + +void MultiresDM_mark_as_modified(DerivedMesh *dm) +{ + ((MultiresDM*)dm)->modified = 1; +} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index dbc94571cad..e98d7bb01a4 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -157,7 +157,7 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; - Cloth *cloth = clmd->clothObject; + Cloth *cloth; ClothVertex *verts; MFace *mfaces; float co[12]; @@ -198,7 +198,7 @@ BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { unsigned int i; BVHTree *bvhtree; - Cloth *cloth = clmd->clothObject; + Cloth *cloth; ClothVertex *verts; MFace *mfaces; float co[12]; @@ -479,7 +479,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /************************************************ * clothModifier_do - main simulation function ************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { DerivedMesh *result; PointCache *cache; @@ -487,12 +487,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh * float timescale; int framedelta, framenr, startframe, endframe; - framenr= (int)G.scene->r.cfra; + clmd->scene= scene; /* nice to pass on later :) */ + framenr= (int)scene->r.cfra; cache= clmd->point_cache; result = CDDM_copy(dm); BKE_ptcache_id_from_cloth(&pid, ob, clmd); - BKE_ptcache_id_time(&pid, framenr, &startframe, &endframe, ×cale); + BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); clmd->sim_parms->timescale= timescale; if(!result) { @@ -786,15 +787,14 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) int j = 0; MDeformVert *dvert = NULL; Cloth *clothObj = NULL; - int numverts = dm->getNumVerts ( dm ); + int numverts; float goalfac = 0; ClothVertex *verts = NULL; + if (!clmd || !dm) return; + clothObj = clmd->clothObject; - if ( !dm ) - return; - numverts = dm->getNumVerts ( dm ); verts = clothObj->verts; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 0b5465ea25d..c122145c98f 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -45,7 +45,6 @@ #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" -#include "mydevice.h" #include "Bullet-C-Api.h" @@ -592,7 +591,9 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap ClothModifierData *clmd = ( ClothModifierData * ) md1; CollisionModifierData *collmd = ( CollisionModifierData * ) md2; MFace *face1=NULL, *face2 = NULL; +#ifdef WITH_BULLET ClothVertex *verts1 = clmd->clothObject->verts; +#endif double distance = 0; float epsilon1 = clmd->coll_parms->epsilon; float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); @@ -1295,7 +1296,7 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col // return all collision objects in scene // collision object will exclude self -CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) +CollisionModifierData **get_collisionobjects(Scene *scene, Object *self, int *numcollobj) { Base *base=NULL; CollisionModifierData **objs = NULL; @@ -1305,7 +1306,7 @@ CollisionModifierData **get_collisionobjects(Object *self, int *numcollobj) objs = MEM_callocN(sizeof(CollisionModifierData *)*maxobj, "CollisionObjectsArray"); // check all collision objects - for ( base = G.scene->base.first; base; base = base->next ) + for ( base = scene->base.first; base; base = base->next ) { /*Only proceed for mesh object in same layer */ if(!(base->object->type==OB_MESH && (base->lay & self->lay))) @@ -1450,7 +1451,7 @@ int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, CollisionModifie } // cloth - object collisions -int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, float dt ) +int cloth_bvh_objcollision (Object *ob, ClothModifierData * clmd, float step, float dt ) { Cloth *cloth=NULL; BVHTree *cloth_bvh=NULL; @@ -1480,7 +1481,7 @@ int cloth_bvh_objcollision ( Object *ob, ClothModifierData * clmd, float step, f bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) - collobjs = get_collisionobjects(ob, &numcollobj); + collobjs = get_collisionobjects(clmd->scene, ob, &numcollobj); if(!collobjs) return 0; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 1bc34aea9a1..e8716aba296 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -32,6 +32,10 @@ #include <stdlib.h> #include <float.h> +#ifdef WITH_LCMS +#include <lcms.h> +#endif + #include "MEM_guardedalloc.h" #include "DNA_color_types.h" @@ -650,6 +654,38 @@ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const vecout[2]= curvemap_evaluateF(cumap->cm+2, fac); } +void colorcorrection_do_ibuf(ImBuf *ibuf, const char *profile) +{ + if (ibuf->crect == NULL) + { +#ifdef WITH_LCMS + cmsHPROFILE imageProfile, proofingProfile; + cmsHTRANSFORM hTransform; + + ibuf->crect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(int), "imbuf crect"); + + imageProfile = cmsCreate_sRGBProfile(); + proofingProfile = cmsOpenProfileFromFile(profile, "r"); + + cmsErrorAction(LCMS_ERROR_SHOW); + + hTransform = cmsCreateProofingTransform(imageProfile, TYPE_RGBA_8, imageProfile, TYPE_RGBA_8, + proofingProfile, + INTENT_ABSOLUTE_COLORIMETRIC, + INTENT_ABSOLUTE_COLORIMETRIC, + cmsFLAGS_SOFTPROOFING); + + cmsDoTransform(hTransform, ibuf->rect, ibuf->crect, ibuf->x * ibuf->y); + + cmsDeleteTransform(hTransform); + cmsCloseProfile(imageProfile); + cmsCloseProfile(proofingProfile); +#else + ibuf->crect = ibuf->rect; +#endif + } +} + void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index f93fc403404..a43389a2ef6 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -31,12 +31,13 @@ #include <stddef.h> #include <string.h> #include <math.h> +#include <float.h> #include "MEM_guardedalloc.h" -#include "nla.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_editVert.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -44,6 +45,7 @@ #include "DNA_object_types.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_lattice_types.h" #include "DNA_scene_types.h" @@ -65,12 +67,13 @@ #include "BKE_library.h" #include "BKE_idprop.h" #include "BKE_shrinkwrap.h" +#include "BKE_mesh.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" #endif -#include "blendef.h" +#include "ED_mesh.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -81,157 +84,6 @@ #endif -/* ******************* Constraint Channels ********************** */ -/* Constraint Channels exist in one of two places: - * - Under Action Channels in an Action (act->chanbase->achan->constraintChannels) - * - Under Object without Object-level Action yet (ob->constraintChannels) - * - * The main purpose that Constraint Channels serve is to act as a link - * between an IPO-block (which provides values to interpolate between for some settings) - */ - -/* ------------ Data Management ----------- */ - -/* Free constraint channels, and reduce the number of users of the related ipo-blocks */ -void free_constraint_channels (ListBase *chanbase) -{ - bConstraintChannel *chan; - - for (chan=chanbase->first; chan; chan=chan->next) { - if (chan->ipo) { - chan->ipo->id.us--; - } - } - - BLI_freelistN(chanbase); -} - -/* Make a copy of the constraint channels from dst to src, and also give the - * new constraint channels their own copy of the original's IPO. - */ -void copy_constraint_channels (ListBase *dst, ListBase *src) -{ - bConstraintChannel *dchan, *schan; - - dst->first = dst->last = NULL; - duplicatelist(dst, src); - - for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) { - dchan->ipo = copy_ipo(schan->ipo); - } -} - -/* Make a copy of the constraint channels from dst to src, but make the - * new constraint channels use the same IPO-data as their twin. - */ -void clone_constraint_channels (ListBase *dst, ListBase *src) -{ - bConstraintChannel *dchan, *schan; - - dst->first = dst->last = NULL; - duplicatelist(dst, src); - - for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) { - id_us_plus((ID *)dchan->ipo); - } -} - -/* ------------- Constraint Channel Tools ------------ */ - -/* Find the constraint channel with a given name */ -bConstraintChannel *get_constraint_channel (ListBase *list, const char name[]) -{ - bConstraintChannel *chan; - - if (list) { - for (chan = list->first; chan; chan=chan->next) { - if (!strcmp(name, chan->name)) { - return chan; - } - } - } - - return NULL; -} - -/* Find or create a new constraint channel */ -bConstraintChannel *verify_constraint_channel (ListBase *list, const char name[]) -{ - bConstraintChannel *chan; - - chan= get_constraint_channel(list, name); - - if (chan == NULL) { - chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint channel"); - BLI_addtail(list, chan); - strcpy(chan->name, name); - } - - return chan; -} - -/* --------- Constraint Channel Evaluation/Execution --------- */ - -/* IPO-system call: calculate IPO-block for constraint channels, and flush that - * info onto the corresponding constraint. - */ -void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, short onlydrivers) -{ - bConstraint *con; - - /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */ - for (con=conbase->first; con; con=con->next) { - Ipo *ipo= NULL; - - if (con->flag & CONSTRAINT_OWN_IPO) - ipo= con->ipo; - else { - bConstraintChannel *chan = get_constraint_channel(chanbase, con->name); - if (chan) ipo= chan->ipo; - } - - if (ipo) { - IpoCurve *icu; - - calc_ipo(ipo, ctime); - - for (icu=ipo->curve.first; icu; icu=icu->next) { - if (!onlydrivers || icu->driver) { - switch (icu->adrcode) { - case CO_ENFORCE: - { - /* Influence is clamped to 0.0f -> 1.0f range */ - con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f); - } - break; - case CO_HEADTAIL: - { - /* we need to check types of constraints that can get this here, as user - * may have created an IPO-curve for this from IPO-editor but for a constraint - * that cannot support this - */ - switch (con->type) { - /* supported constraints go here... */ - case CONSTRAINT_TYPE_LOCLIKE: - case CONSTRAINT_TYPE_TRACKTO: - case CONSTRAINT_TYPE_MINMAX: - case CONSTRAINT_TYPE_STRETCHTO: - case CONSTRAINT_TYPE_DISTLIMIT: - con->headtail = icu->curval; - break; - - default: - /* not supported */ - break; - } - } - break; - } - } - } - } - } -} /* ************************ Constraints - General Utilities *************************** */ /* These functions here don't act on any specific constraints, and are therefore should/will @@ -244,20 +96,23 @@ void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, /* Find the first available, non-duplicate name for a given constraint */ void unique_constraint_name (bConstraint *con, ListBase *list) { - BLI_uniquename(list, con, "Const", offsetof(bConstraint, name), 32); + BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), 32); } /* ----------------- Evaluation Loop Preparation --------------- */ /* package an object/bone for use in constraint evaluation */ /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */ -bConstraintOb *constraints_make_evalob (Object *ob, void *subdata, short datatype) +bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata, short datatype) { bConstraintOb *cob; /* create regardless of whether we have any data! */ cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb"); + /* for system time, part of deglobalization, code nicer later with local time (ton) */ + cob->scene= scene; + /* based on type of available data */ switch (datatype) { case CONSTRAINT_OBTYPE_OBJECT: @@ -535,9 +390,11 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 /* ------------ General Target Matrix Tools ---------- */ /* function that sets the given matrix based on given vertex group in mesh */ -static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4]) +static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, float mat[][4]) { DerivedMesh *dm; + Mesh *me= ob->data; + EditMesh *em = BKE_mesh_get_editmesh(me); float vec[3] = {0.0f, 0.0f, 0.0f}, tvec[3]; float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; float imat[3][3], tmat[3][3]; @@ -552,9 +409,9 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4]) if (dgroup < 0) return; /* get DerivedMesh */ - if ((G.obedit == ob) && (G.editMesh)) { + if (em) { /* target is in editmode, so get a special derived mesh */ - dm = CDDM_from_editmesh(G.editMesh, ob->data); + dm = CDDM_from_editmesh(em, ob->data); freeDM= 1; } else { @@ -563,7 +420,7 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4]) * (this is more effficient + sufficient for most cases) */ if (ob->lastDataMask != CD_MASK_DERIVEDMESH) { - dm = mesh_get_derived_final(ob, CD_MASK_DERIVEDMESH); + dm = mesh_get_derived_final(scene, ob, CD_MASK_DERIVEDMESH); freeDM= 1; } else @@ -632,9 +489,11 @@ static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4]) } } - /* free temporary DerivedMesh created */ - if (dm && freeDM) + /* free temporary DerivedMesh created (in EditMode case) */ + if (dm && freeDM) dm->release(dm); + if (em) + BKE_mesh_end_editmesh(me, em); } /* function that sets the given matrix based on given vertex group in lattice */ @@ -696,7 +555,7 @@ static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][ /* generic function to get the appropriate matrix for most target cases */ /* The cases where the target can be object data have not been implemented */ -static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][4], short from, short to, float headtail) +static void constraint_target_to_mat4 (Scene *scene, Object *ob, char *substring, float mat[][4], short from, short to, float headtail) { /* Case OBJECT */ if (!strlen(substring)) { @@ -713,7 +572,7 @@ static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][ * way as constraints can only really affect things on object/bone level. */ else if (ob->type == OB_MESH) { - contarget_get_mesh_mat(ob, substring, mat); + contarget_get_mesh_mat(scene, ob, substring, mat); constraint_mat_convertspace(ob, NULL, mat, from, to); } else if (ob->type == OB_LATTICE) { @@ -795,7 +654,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = { static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float ctime) { if (VALID_CONS_TARGET(ct)) - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); + constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); else if (ct) Mat4One(ct->matrix); } @@ -1210,7 +1069,7 @@ static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstra bKinematicConstraint *data= con->data; if (VALID_CONS_TARGET(ct)) - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); + constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); else if (ct) { if (data->flag & CONSTRAINT_IK_AUTO) { Object *ob= cob->ob; @@ -1304,15 +1163,17 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr /* only happens on reload file, but violates depsgraph still... fix! */ if (cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(ct->tar, 0); + makeDispListCurveTypes(cob->scene, ct->tar, 0); if (cu->path && cu->path->data) { - curvetime= bsystem_time(ct->tar, (float)ctime, 0.0) - data->offset; + curvetime= bsystem_time(cob->scene, ct->tar, (float)ctime, 0.0) - data->offset; +#if 0 // XXX old animation system if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) { curvetime /= cu->pathlen; CLAMP(curvetime, 0.0, 1.0); } +#endif // XXX old animation system if ( where_on_path(ct->tar, curvetime, vec, dir) ) { if (data->followflag) { @@ -1854,7 +1715,7 @@ static void pycon_copy (bConstraint *con, bConstraint *srccon) bPythonConstraint *opycon = (bPythonConstraint *)srccon->data; pycon->prop = IDP_CopyProperty(opycon->prop); - duplicatelist(&pycon->targets, &opycon->targets); + BLI_duplicatelist(&pycon->targets, &opycon->targets); } static void pycon_new_data (void *cdata) @@ -1892,13 +1753,13 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT /* this check is to make sure curve objects get updated on file load correctly.*/ if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */ - makeDispListCurveTypes(ct->tar, 0); + makeDispListCurveTypes(cob->scene, ct->tar, 0); } /* firstly calculate the matrix the normal way, then let the py-function override * this matrix if it needs to do so */ - constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); + constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); /* only execute target calculation if allowed */ #ifndef DISABLE_PYTHON @@ -2005,7 +1866,7 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint Mat4One(ct->matrix); /* get the transform matrix of the target */ - constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); + constraint_target_to_mat4(cob->scene, ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); /* determine where in transform range target is */ /* data->type is mapped as follows for backwards compatability: @@ -2037,28 +1898,38 @@ static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraint CLAMP(s, 0, 1); t = ( s * (data->end-data->start)) + data->start; + if (G.f & G_DEBUG) + printf("do Action Constraint %s - Ob %s Pchan %s \n", con->name, cob->ob->id.name+2, (cob->pchan)?cob->pchan->name:NULL); + /* Get the appropriate information from the action */ if (cob->type == CONSTRAINT_OBTYPE_BONE) { + Object workob; bPose *pose; bPoseChannel *pchan, *tchan; /* make a temporary pose and evaluate using that */ pose = MEM_callocN(sizeof(bPose), "pose"); + /* make a copy of the bone of interest in the temp pose before evaluating action, so that it can get set */ pchan = cob->pchan; tchan= verify_pose_channel(pose, pchan->name); - extract_pose_from_action(pose, data->act, t); - chan_calc_mat(tchan); + /* evaluate action using workob (it will only set the PoseChannel in question) */ + what_does_obaction(cob->scene, cob->ob, &workob, pose, data->act, pchan->name, t); + /* convert animation to matrices for use here */ + chan_calc_mat(tchan); Mat4CpyMat4(ct->matrix, tchan->chan_mat); /* Clean up */ free_pose(pose); } else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) { + Object workob; + /* evaluate using workob */ - what_does_obaction(cob->ob, data->act, t); + // FIXME: we don't have any consistent standards on limiting effects on object... + what_does_obaction(cob->scene, cob->ob, &workob, NULL, data->act, NULL, t); object_to_mat4(&workob, ct->matrix); } else { @@ -2973,7 +2844,7 @@ static void clampto_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain /* only happens on reload file, but violates depsgraph still... fix! */ if (cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(ct->tar, 0); + makeDispListCurveTypes(cob->scene, ct->tar, 0); } /* technically, this isn't really needed for evaluation, but we don't know what else @@ -3033,44 +2904,53 @@ static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta float len= (curveMax[clamp_axis] - curveMin[clamp_axis]); float offset; - /* find bounding-box range where target is located */ - if (ownLoc[clamp_axis] < curveMin[clamp_axis]) { - /* bounding-box range is before */ - offset= curveMin[clamp_axis]; - - while (ownLoc[clamp_axis] < offset) - offset -= len; - - /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */ - curvetime = (ownLoc[clamp_axis] - offset) / (len); - } - else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) { - /* bounding-box range is after */ - offset= curveMax[clamp_axis]; - - while (ownLoc[clamp_axis] > offset) { - if ((offset + len) > ownLoc[clamp_axis]) - break; - else - offset += len; + /* check to make sure len is not so close to zero that it'll cause errors */ + if (IS_EQ(len, 0) == 0) { + /* find bounding-box range where target is located */ + if (ownLoc[clamp_axis] < curveMin[clamp_axis]) { + /* bounding-box range is before */ + offset= curveMin[clamp_axis]; + + while (ownLoc[clamp_axis] < offset) + offset -= len; + + /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */ + curvetime = (ownLoc[clamp_axis] - offset) / (len); + } + else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) { + /* bounding-box range is after */ + offset= curveMax[clamp_axis]; + + while (ownLoc[clamp_axis] > offset) { + if ((offset + len) > ownLoc[clamp_axis]) + break; + else + offset += len; + } + + /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */ + curvetime = (ownLoc[clamp_axis] - offset) / (len); + } + else { + /* as the location falls within bounds, just calculate */ + curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len); } - - /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */ - curvetime = (ownLoc[clamp_axis] - offset) / (len); } else { - /* as the location falls within bounds, just calculate */ - curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len); + /* as length is close to zero, curvetime by default should be 0 (i.e. the start) */ + curvetime= 0.0f; } } else { /* no cyclic, so position is clamped to within the bounding box */ if (ownLoc[clamp_axis] <= curveMin[clamp_axis]) - curvetime = 0.0; + curvetime = 0.0f; else if (ownLoc[clamp_axis] >= curveMax[clamp_axis]) - curvetime = 1.0; - else + curvetime = 1.0f; + else if ( IS_EQ((curveMax[clamp_axis] - curveMin[clamp_axis]), 0) == 0 ) curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]); + else + curvetime = 0.0f; } /* 3. position on curve */ @@ -3281,7 +3161,7 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr float dist; SpaceTransform transform; - DerivedMesh *target = object_get_derived_final(ct->tar, CD_MASK_BAREMESH); + DerivedMesh *target = object_get_derived_final(cob->scene, ct->tar, CD_MASK_BAREMESH); BVHTreeRayHit hit; BVHTreeNearest nearest; @@ -3402,7 +3282,7 @@ static bConstraintTypeInfo CTI_SHRINKWRAP = { /* ************************* Constraints Type-Info *************************** */ /* All of the constraints api functions use bConstraintTypeInfo structs to carry out - * and operations that involve constraint specifc code. + * and operations that involve constraint specific code. */ /* These globals only ever get directly accessed in this file */ @@ -3494,17 +3374,16 @@ void free_constraint_data (bConstraint *con) } /* Free all constraints from a constraint-stack */ -void free_constraints (ListBase *conlist) +void free_constraints (ListBase *list) { bConstraint *con; /* Free constraint data and also any extra data */ - for (con= conlist->first; con; con= con->next) { + for (con= list->first; con; con= con->next) free_constraint_data(con); - } /* Free the whole list */ - BLI_freelistN(conlist); + BLI_freelistN(list); } /* Reassign links that constraints have to other data (called during file loading?) */ @@ -3543,20 +3422,39 @@ void copy_constraints (ListBase *dst, ListBase *src) bConstraint *con, *srccon; dst->first= dst->last= NULL; - duplicatelist(dst, src); + BLI_duplicatelist(dst, src); - for (con=dst->first, srccon=src->first; con; srccon=srccon->next, con=con->next) { + for (con=dst->first, srccon=src->first; con && srccon; srccon=srccon->next, con=con->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); + id_us_plus((ID *)con->ipo); + /* only do specific constraints if required */ if (cti && cti->copy_data) cti->copy_data(con, srccon); } } +/* finds the 'active' constraint in a constraint stack */ +bConstraint *constraints_get_active (ListBase *list) +{ + bConstraint *con; + + /* search for the first constraint with the 'active' flag set */ + if (list) { + for (con= list->first; con; con= con->next) { + if (con->flag & CONSTRAINT_ACTIVE) + return con; + } + } + + /* no active constraint found */ + return NULL; +} + /* -------- Constraints and Proxies ------- */ /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */ @@ -3706,7 +3604,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) if (con->enforce == 0.0f) continue; /* influence of constraint - * - value should have been set from IPO's/Constraint Channels already + * - value should have been set from animation data already */ enf = con->enforce; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c new file mode 100644 index 00000000000..ae541365b1e --- /dev/null +++ b/source/blender/blenkernel/intern/context.c @@ -0,0 +1,595 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation (2008). + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_access.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BKE_context.h" +#include "BKE_main.h" +#include "BKE_screen.h" + +#include <string.h> + +/* struct */ + +struct bContext { + int thread; + + /* windowmanager context */ + struct { + struct wmWindowManager *manager; + struct wmWindow *window; + struct bScreen *screen; + struct ScrArea *area; + struct ARegion *region; + struct ARegion *menu; + struct bContextStore *store; + } wm; + + /* data context */ + struct { + struct Main *main; + struct Scene *scene; + + int recursion; + } data; + + /* data evaluation */ + struct { + int render; + } eval; +}; + +/* context */ + +bContext *CTX_create() +{ + bContext *C; + + C= MEM_callocN(sizeof(bContext), "bContext"); + + return C; +} + +bContext *CTX_copy(const bContext *C) +{ + bContext *newC= MEM_dupallocN((void*)C); + + return newC; +} + +void CTX_free(bContext *C) +{ + MEM_freeN(C); +} + +/* store */ + +bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr) +{ + bContextStoreEntry *entry; + bContextStore *ctx, *lastctx; + + /* ensure we have a context to put the entry in, if it was already used + * we have to copy the context to ensure */ + ctx= contexts->last; + + if(!ctx || ctx->used) { + if(ctx) { + lastctx= ctx; + ctx= MEM_dupallocN(lastctx); + BLI_duplicatelist(&ctx->entries, &lastctx->entries); + } + else + ctx= MEM_callocN(sizeof(bContextStore), "bContextStore"); + + BLI_addtail(contexts, ctx); + } + + entry= MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry"); + BLI_strncpy(entry->name, name, sizeof(entry->name)); + entry->ptr= *ptr; + + BLI_addtail(&ctx->entries, entry); + + return ctx; +} + +void CTX_store_set(bContext *C, bContextStore *store) +{ + C->wm.store= store; +} + +bContextStore *CTX_store_copy(bContextStore *store) +{ + bContextStore *ctx; + + ctx= MEM_dupallocN(store); + BLI_duplicatelist(&ctx->entries, &store->entries); + + return ctx; +} + +void CTX_store_free(bContextStore *store) +{ + BLI_freelistN(&store->entries); + MEM_freeN(store); +} + +void CTX_store_free_list(ListBase *contexts) +{ + bContextStore *ctx; + + while((ctx= contexts->first)) { + BLI_remlink(contexts, ctx); + CTX_store_free(ctx); + } +} + +/* window manager context */ + +wmWindowManager *CTX_wm_manager(const bContext *C) +{ + return C->wm.manager; +} + +wmWindow *CTX_wm_window(const bContext *C) +{ + return C->wm.window; +} + +bScreen *CTX_wm_screen(const bContext *C) +{ + return C->wm.screen; +} + +ScrArea *CTX_wm_area(const bContext *C) +{ + return C->wm.area; +} + +SpaceLink *CTX_wm_space_data(const bContext *C) +{ + return (C->wm.area)? C->wm.area->spacedata.first: NULL; +} + +ARegion *CTX_wm_region(const bContext *C) +{ + return C->wm.region; +} + +void *CTX_wm_region_data(const bContext *C) +{ + return (C->wm.region)? C->wm.region->regiondata: NULL; +} + +struct ARegion *CTX_wm_menu(const bContext *C) +{ + return C->wm.menu; +} + +View3D *CTX_wm_view3d(const bContext *C) +{ + if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D) + return C->wm.area->spacedata.first; + return NULL; +} + +RegionView3D *CTX_wm_region_view3d(const bContext *C) +{ + if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D) + if(C->wm.region) + return C->wm.region->regiondata; + return NULL; +} + +struct SpaceText *CTX_wm_space_text(const bContext *C) +{ + if(C->wm.area && C->wm.area->spacetype==SPACE_TEXT) + return C->wm.area->spacedata.first; + return NULL; +} + +struct SpaceImage *CTX_wm_space_image(const bContext *C) +{ + if(C->wm.area && C->wm.area->spacetype==SPACE_IMAGE) + return C->wm.area->spacedata.first; + return NULL; +} + +void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) +{ + C->wm.manager= wm; + C->wm.window= NULL; + C->wm.screen= NULL; + C->wm.area= NULL; + C->wm.region= NULL; +} + +void CTX_wm_window_set(bContext *C, wmWindow *win) +{ + C->wm.window= win; + C->wm.screen= (win)? win->screen: NULL; + C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; + C->wm.area= NULL; + C->wm.region= NULL; +} + +void CTX_wm_screen_set(bContext *C, bScreen *screen) +{ + C->wm.screen= screen; + C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; + C->wm.area= NULL; + C->wm.region= NULL; +} + +void CTX_wm_area_set(bContext *C, ScrArea *area) +{ + C->wm.area= area; + C->wm.region= NULL; +} + +void CTX_wm_region_set(bContext *C, ARegion *region) +{ + C->wm.region= region; +} + +void CTX_wm_menu_set(bContext *C, ARegion *menu) +{ + C->wm.menu= menu; +} + +/* data context utility functions */ + +struct bContextDataResult { + PointerRNA ptr; + ListBase list; +}; + +static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result) +{ + int done= 0, recursion= C->data.recursion; + + memset(result, 0, sizeof(bContextDataResult)); + + /* we check recursion to ensure that we do not get infinite + * loops requesting data from ourselfs in a context callback */ + if(!done && recursion < 1 && C->wm.store) { + bContextStoreEntry *entry; + + C->data.recursion= 1; + + for(entry=C->wm.store->entries.first; entry; entry=entry->next) { + if(strcmp(entry->name, member) == 0) { + result->ptr= entry->ptr; + done= 1; + } + } + } + if(!done && recursion < 2 && C->wm.region) { + C->data.recursion= 2; + if(C->wm.region->type && C->wm.region->type->context) + done= C->wm.region->type->context(C, member, result); + } + if(!done && recursion < 3 && C->wm.area) { + C->data.recursion= 3; + if(C->wm.area->type && C->wm.area->type->context) + done= C->wm.area->type->context(C, member, result); + } + if(!done && recursion < 4 && C->wm.screen) { + bContextDataCallback cb= C->wm.screen->context; + C->data.recursion= 4; + if(cb) + done= cb(C, member, result); + } + + C->data.recursion= recursion; + + return done; +} + +static void *ctx_data_pointer_get(const bContext *C, const char *member) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) + return result.ptr.data; + + return NULL; +} + +static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) { + *pointer= result.ptr.data; + return 1; + } + else { + *pointer= NULL; + return 0; + } +} + +static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) { + *list= result.list; + return 1; + } + + return 0; +} + +PointerRNA CTX_data_pointer_get(bContext *C, const char *member) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) { + return result.ptr; + } + else { + PointerRNA ptr; + memset(&ptr, 0, sizeof(ptr)); + return ptr; + } + +} + +ListBase CTX_data_collection_get(bContext *C, const char *member) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) { + return result.list; + } + else { + ListBase list; + memset(&list, 0, sizeof(list)); + return list; + } +} + +void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) +{ + bContextDataResult result; + + if(ctx_data_get((bContext*)C, member, &result)) { + *r_ptr= result.ptr; + *r_lb= result.list; + } + else { + memset(r_ptr, 0, sizeof(*r_ptr)); + memset(r_lb, 0, sizeof(*r_lb)); + } +} + +int CTX_data_equals(const char *member, const char *str) +{ + return (strcmp(member, str) == 0); +} + +void CTX_data_id_pointer_set(bContextDataResult *result, ID *id) +{ + RNA_id_pointer_create(id, &result->ptr); +} + +void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data) +{ + RNA_pointer_create(id, type, data, &result->ptr); +} + +void CTX_data_id_list_add(bContextDataResult *result, ID *id) +{ + CollectionPointerLink *link; + + link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add"); + RNA_id_pointer_create(id, &link->ptr); + + BLI_addtail(&result->list, link); +} + +void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data) +{ + CollectionPointerLink *link; + + link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add"); + RNA_pointer_create(id, type, data, &link->ptr); + + BLI_addtail(&result->list, link); +} + +int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*)) +{ + ListBase list; + + if(func(C, &list)) { + int tot= BLI_countlist(&list); + BLI_freelistN(&list); + return tot; + } + else + return 0; +} + +/* data context */ + +Main *CTX_data_main(const bContext *C) +{ + Main *bmain; + + if(ctx_data_pointer_verify(C, "main", (void*)&bmain)) + return bmain; + else + return C->data.main; +} + +void CTX_data_main_set(bContext *C, Main *bmain) +{ + C->data.main= bmain; +} + +Scene *CTX_data_scene(const bContext *C) +{ + Scene *scene; + + if(ctx_data_pointer_verify(C, "scene", (void*)&scene)) + return scene; + else + return C->data.scene; +} + +void CTX_data_scene_set(bContext *C, Scene *scene) +{ + C->data.scene= scene; +} + +ToolSettings *CTX_data_tool_settings(const bContext *C) +{ + Scene *scene = CTX_data_scene(C); + + if(scene) + return scene->toolsettings; + else + return NULL; +} + +int CTX_data_selected_nodes(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_nodes", list); +} + +int CTX_data_selected_editable_objects(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_editable_objects", list); +} + +int CTX_data_selected_editable_bases(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_editable_bases", list); +} + +int CTX_data_selected_objects(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_objects", list); +} + +int CTX_data_selected_bases(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_bases", list); +} + +int CTX_data_visible_objects(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "visible_objects", list); +} + +int CTX_data_visible_bases(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "visible_bases", list); +} + +struct Object *CTX_data_active_object(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_object"); +} + +struct Base *CTX_data_active_base(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_base"); +} + +struct Object *CTX_data_edit_object(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_object"); +} + +struct Image *CTX_data_edit_image(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_image"); +} + +struct Text *CTX_data_edit_text(const bContext *C) +{ + return ctx_data_pointer_get(C, "edit_text"); +} + +struct EditBone *CTX_data_active_bone(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_bone"); +} + +int CTX_data_selected_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_bones", list); +} + +int CTX_data_selected_editable_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_editable_bones", list); +} + +int CTX_data_visible_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "visible_bones", list); +} + +int CTX_data_editable_bones(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "editable_bones", list); +} + +struct bPoseChannel *CTX_data_active_pchan(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_pchan"); +} + +int CTX_data_selected_pchans(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "selected_pchans", list); +} + +int CTX_data_visible_pchans(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "visible_pchans", list); +} + diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0d6382a8d37..fab9669d55f 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -48,27 +48,26 @@ /* for dereferencing pointers */ #include "DNA_ID.h" -#include "DNA_vfont_types.h" #include "DNA_key_types.h" -#include "DNA_ipo_types.h" +#include "DNA_scene_types.h" +#include "DNA_vfont_types.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_utildefines.h" // VECCOPY -#include "BKE_object.h" -#include "BKE_mesh.h" +#include "BKE_animsys.h" +#include "BKE_anim.h" #include "BKE_curve.h" #include "BKE_displist.h" -#include "BKE_ipo.h" -#include "BKE_anim.h" -#include "BKE_library.h" +#include "BKE_font.h" +#include "BKE_global.h" #include "BKE_key.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" // VECCOPY /* globals */ -extern ListBase editNurb; /* editcurve.c */ - /* local */ int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, @@ -86,20 +85,42 @@ void unlink_curve(Curve *cu) cu->vfont= 0; if(cu->key) cu->key->id.us--; cu->key= 0; - if(cu->ipo) cu->ipo->id.us--; - cu->ipo= 0; } +/* frees editcurve entirely */ +void BKE_free_editfont(Curve *cu) +{ + if(cu->editfont) { + EditFont *ef= cu->editfont; + + if(ef->oldstr) MEM_freeN(ef->oldstr); + if(ef->oldstrinfo) MEM_freeN(ef->oldstrinfo); + if(ef->textbuf) MEM_freeN(ef->textbuf); + if(ef->textbufinfo) MEM_freeN(ef->textbufinfo); + if(ef->copybuf) MEM_freeN(ef->copybuf); + if(ef->copybufinfo) MEM_freeN(ef->copybufinfo); + + MEM_freeN(ef); + cu->editfont= NULL; + } +} -/* niet curve zelf vrijgeven */ +/* don't free curve itself */ void free_curve(Curve *cu) { - freeNurblist(&cu->nurb); BLI_freelistN(&cu->bev); freedisplist(&cu->disp); + BKE_free_editfont(cu); + if(cu->editnurb) { + freeNurblist(cu->editnurb); + MEM_freeN(cu->editnurb); + cu->editnurb= NULL; + } + unlink_curve(cu); + BKE_free_animdata((ID *)cu); if(cu->mat) MEM_freeN(cu->mat); if(cu->str) MEM_freeN(cu->str); @@ -128,6 +149,18 @@ Curve *add_curve(char *name, int type) cu->bb= unit_boundbox(); + if(type==OB_FONT) { + cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font(); + cu->vfont->id.us+=4; + cu->str= MEM_mallocN(12, "str"); + strcpy(cu->str, "Text"); + cu->pos= 4; + cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo"); + cu->totbox= cu->actbox= 1; + cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox"); + cu->tb[0].w = cu->tb[0].h = 0.0; + } + return cu; } @@ -157,8 +190,12 @@ Curve *copy_curve(Curve *cu) cun->bev.first= cun->bev.last= 0; cun->path= 0; + cun->editnurb= NULL; + +#if 0 // XXX old animation system /* single user ipo too */ if(cun->ipo) cun->ipo= copy_ipo(cun->ipo); +#endif // XXX old animation system id_us_plus((ID *)cun->vfont); id_us_plus((ID *)cun->vfontb); @@ -1033,7 +1070,7 @@ float *make_orco_surf(Object *ob) /* NOTE: This routine is tied to the order of vertex * built by displist and as passed to the renderer. */ -float *make_orco_curve(Object *ob) +float *make_orco_curve(Scene *scene, Object *ob) { Curve *cu = ob->data; DispList *dl; @@ -1043,7 +1080,7 @@ float *make_orco_curve(Object *ob) if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) { cp_cu_key(cu, cu->key->refkey, 0, count_curveverts(&cu->nurb)); - makeDispListCurveTypes(ob, 1); + makeDispListCurveTypes(scene, ob, 1); remakeDisp = 1; } @@ -1116,7 +1153,7 @@ float *make_orco_curve(Object *ob) } if (remakeDisp) { - makeDispListCurveTypes(ob, 0); + makeDispListCurveTypes(scene, ob, 0); } return coord_array; @@ -1125,7 +1162,7 @@ float *make_orco_curve(Object *ob) /* ***************** BEVEL ****************** */ -void makebevelcurve(Object *ob, ListBase *disp) +void makebevelcurve(Scene *scene, Object *ob, ListBase *disp) { DispList *dl, *dlnew; Curve *bevcu, *cu; @@ -1136,7 +1173,7 @@ void makebevelcurve(Object *ob, ListBase *disp) disp->first = disp->last = NULL; /* if a font object is being edited, then do nothing */ - if( ob == G.obedit && ob->type == OB_FONT ) return; +// XXX if( ob == obedit && ob->type == OB_FONT ) return; if(cu->bevobj && cu->bevobj!=ob) { if(cu->bevobj->type==OB_CURVE) { @@ -1147,7 +1184,7 @@ void makebevelcurve(Object *ob, ListBase *disp) dl= bevcu->disp.first; if(dl==0) { - makeDispListCurveTypes(cu->bevobj, 0); + makeDispListCurveTypes(scene, cu->bevobj, 0); dl= bevcu->disp.first; } while(dl) { @@ -1529,7 +1566,7 @@ void makeBevelList(Object *ob) /* STEP 1: MAKE POLYS */ BLI_freelistN(&(cu->bev)); - if(ob==G.obedit && ob->type!=OB_FONT) nu= editNurb.first; + if(cu->editnurb && ob->type!=OB_FONT) nu= cu->editnurb->first; else nu= cu->nurb.first; while(nu) { @@ -1976,7 +2013,7 @@ void makeBevelList(Object *ob) * 1: nothing, 1:auto, 2:vector, 3:aligned */ -/* mode: is not zero when IpoCurve, is 2 when forced horizontal for autohandles */ +/* mode: is not zero when FCurve, is 2 when forced horizontal for autohandles */ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode) { float *p1,*p2,*p3, pt[3]; @@ -2307,18 +2344,18 @@ void autocalchandlesNurb(Nurb *nu, int flag) calchandlesNurb(nu); } -void autocalchandlesNurb_all(int flag) +void autocalchandlesNurb_all(ListBase *editnurb, int flag) { Nurb *nu; - nu= editNurb.first; + nu= editnurb->first; while(nu) { autocalchandlesNurb(nu, flag); nu= nu->next; } } -void sethandlesNurb(short code) +void sethandlesNurb(ListBase *editnurb, short code) { /* code==1: set autohandle */ /* code==2: set vectorhandle */ @@ -2331,7 +2368,7 @@ void sethandlesNurb(short code) short a, ok=0; if(code==1 || code==2) { - nu= editNurb.first; + nu= editnurb->first; while(nu) { if( (nu->type & 7)==CU_BEZIER) { bezt= nu->bezt; @@ -2355,7 +2392,7 @@ void sethandlesNurb(short code) else { /* there is 1 handle not FREE: FREE it all, else make ALIGNED */ - nu= editNurb.first; + nu= editnurb->first; if (code == 5) { ok = HD_ALIGN; } else if (code == 6) { @@ -2378,7 +2415,7 @@ void sethandlesNurb(short code) if(ok) ok= HD_FREE; else ok= HD_ALIGN; } - nu= editNurb.first; + nu= editnurb->first; while(nu) { if( (nu->type & 7)==CU_BEZIER) { bezt= nu->bezt; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 05271aa59a7..705d0b66d7f 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -33,7 +33,8 @@ */ #include "BKE_customdata.h" - +#include "BKE_utildefines.h" // CLAMP +#include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_mempool.h" @@ -44,6 +45,7 @@ #include "MEM_guardedalloc.h" +#include <math.h> #include <string.h> /* number of layers to add when growing a CustomData object */ @@ -378,6 +380,156 @@ static void layerDefault_origspace_face(void *data, int count) for(i = 0; i < count; i++) osf[i] = default_osf; } + +/* Adapted from sculptmode.c */ +static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) +{ + int x, y, x2, y2; + const int st_max = st - 1; + float urat, vrat, uopp; + float d[4][3], d2[2][3]; + + if(u < 0) + u = 0; + else if(u >= st) + u = st_max; + if(v < 0) + v = 0; + else if(v >= st) + v = st_max; + + x = floor(u); + y = floor(v); + x2 = x + 1; + y2 = y + 1; + + if(x2 >= st) x2 = st_max; + if(y2 >= st) y2 = st_max; + + urat = u - x; + vrat = v - y; + uopp = 1 - urat; + + VecCopyf(d[0], disps[y * st + x]); + VecCopyf(d[1], disps[y * st + x2]); + VecCopyf(d[2], disps[y2 * st + x]); + VecCopyf(d[3], disps[y2 * st + x2]); + VecMulf(d[0], uopp); + VecMulf(d[1], urat); + VecMulf(d[2], uopp); + VecMulf(d[3], urat); + + VecAddf(d2[0], d[0], d[1]); + VecAddf(d2[1], d[2], d[3]); + VecMulf(d2[0], 1 - vrat); + VecMulf(d2[1], vrat); + + VecAddf(out, d2[0], d2[1]); +} + +static void layerSwap_mdisps(void *data, int *ci) +{ + MDisps *s = data; + float (*d)[3] = NULL; + int x, y, st; + + if(!(ci[0] == 2 && ci[1] == 3 && ci[2] == 0 && ci[3] == 1)) return; + + d = MEM_callocN(sizeof(float) * 3 * s->totdisp, "mdisps swap"); + st = sqrt(s->totdisp); + + for(y = 0; y < st; ++y) { + for(x = 0; x < st; ++x) { + VecCopyf(d[(st - y - 1) * st + (st - x - 1)], s->disps[y * st + x]); + } + } + + if(s->disps) + MEM_freeN(s->disps); + s->disps = d; +} + +static void layerInterp_mdisps(void **sources, float *weights, float *sub_weights, + int count, void *dest) +{ + MDisps *d = dest; + MDisps *s = NULL; + int st, stl; + int i, x, y; + float crn[4][2]; + float (*sw)[4] = NULL; + + /* Initialize the destination */ + for(i = 0; i < d->totdisp; ++i) { + float z[3] = {0,0,0}; + VecCopyf(d->disps[i], z); + } + + /* For now, some restrictions on the input */ + if(count != 1 || !sub_weights) return; + + st = sqrt(d->totdisp); + stl = st - 1; + + sw = (void*)sub_weights; + for(i = 0; i < 4; ++i) { + crn[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3]; + crn[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3]; + } + + s = sources[0]; + for(y = 0; y < st; ++y) { + for(x = 0; x < st; ++x) { + /* One suspects this code could be cleaner. */ + float xl = (float)x / (st - 1); + float yl = (float)y / (st - 1); + float mid1[2] = {crn[0][0] * (1 - xl) + crn[1][0] * xl, + crn[0][1] * (1 - xl) + crn[1][1] * xl}; + float mid2[2] = {crn[3][0] * (1 - xl) + crn[2][0] * xl, + crn[3][1] * (1 - xl) + crn[2][1] * xl}; + float mid3[2] = {mid1[0] * (1 - yl) + mid2[0] * yl, + mid1[1] * (1 - yl) + mid2[1] * yl}; + + float srcdisp[3]; + + mdisps_bilinear(srcdisp, s->disps, st, mid3[0], mid3[1]); + VecCopyf(d->disps[y * st + x], srcdisp); + } + } +} + +static void layerCopy_mdisps(const void *source, void *dest, int count) +{ + int i; + const MDisps *s = source; + MDisps *d = dest; + + for(i = 0; i < count; ++i) { + if(s[i].disps) { + d[i].disps = MEM_dupallocN(s[i].disps); + d[i].totdisp = s[i].totdisp; + } + else { + d[i].disps = NULL; + d[i].totdisp = 0; + } + + } +} + +static void layerFree_mdisps(void *data, int count, int size) +{ + int i; + MDisps *d = data; + + for(i = 0; i < count; ++i) { + if(d[i].disps) + MEM_freeN(d[i].disps); + d[i].disps = NULL; + d[i].totdisp = 0; + } +} + /* --------- */ static void layerDefault_mloopcol(void *data, int count) @@ -421,6 +573,14 @@ static void layerInterp_mloopcol(void **sources, float *weights, col.b += src->b * weight; } } + + /* Subdivide smooth or fractal can cause problems without clamping + * although weights should also not cause this situation */ + CLAMP(col.a, 0.0f, 255.0f); + CLAMP(col.r, 0.0f, 255.0f); + CLAMP(col.g, 0.0f, 255.0f); + CLAMP(col.b, 0.0f, 255.0f); + mc->a = (int)col.a; mc->r = (int)col.r; mc->g = (int)col.g; @@ -496,6 +656,14 @@ static void layerInterp_mcol(void **sources, float *weights, } for(j = 0; j < 4; ++j) { + + /* Subdivide smooth or fractal can cause problems without clamping + * although weights should also not cause this situation */ + CLAMP(col[j].a, 0.0f, 255.0f); + CLAMP(col[j].r, 0.0f, 255.0f); + CLAMP(col[j].g, 0.0f, 255.0f); + CLAMP(col[j].b, 0.0f, 255.0f); + mc[j].a = (int)col[j].a; mc[j].r = (int)col[j].r; mc[j].g = (int)col[j].g; @@ -553,27 +721,32 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL}, {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL}, {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, - {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} + {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL}, + {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, + layerSwap_mcol, layerDefault_mcol}, }; const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty", - "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"}; + "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", + "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol"}; const CustomDataMask CD_MASK_BAREMESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE; const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | - CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT; + CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL; const CustomDataMask CD_MASK_BMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR; const CustomDataMask CD_MASK_FACECORNERS = @@ -626,7 +799,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, number++; if(layer->flag & CD_FLAG_NOCOPY) continue; - else if(!(mask & (1 << type))) continue; + else if(!((int)mask & (int)(1 << (int)type))) continue; else if(number < CustomData_number_of_layers(dest, type)) continue; if((alloctype == CD_ASSIGN) && (layer->flag & CD_FLAG_NOFREE)) @@ -1144,7 +1317,7 @@ void CustomData_set_only_copy(const struct CustomData *data, int i; for(i = 0; i < data->totlayer; ++i) - if(!(mask & (1 << data->layers[i].type))) + if(!((int)mask & (int)(1 << (int)data->layers[i].type))) data->layers[i].flag |= CD_FLAG_NOCOPY; } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 59619b25f8b..dfe3b7ea279 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -33,11 +33,10 @@ #include "BLI_winstuff.h" #endif -//#include "BMF_Api.h" - #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_curve_types.h" @@ -54,7 +53,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_object_fluidsim.h" -#include "DNA_oops_types.h" +#include "DNA_outliner_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -77,7 +76,6 @@ #include "BKE_scene.h" #include "MEM_guardedalloc.h" -#include "blendef.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" @@ -303,61 +301,49 @@ DagForest * dag_init() return forest; } -static void dag_add_driver_relation(Ipo *ipo, DagForest *dag, DagNode *node, int isdata) +/* isdata = object data... */ +// XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... +static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata) { - IpoCurve *icu; + FCurve *fcu; DagNode *node1; - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->driver) { - - if (icu->driver->type == IPO_DRIVER_TYPE_PYTHON) { - - if ((icu->driver->flag & IPO_DRIVER_FLAG_INVALID) || (icu->driver->name[0] == '\0')) - continue; /* empty or invalid expression */ -#ifndef DISABLE_PYTHON - else { - /* now we need refs to all objects mentioned in this - * pydriver expression, to call 'dag_add_relation' - * for each of them */ - Object **obarray = BPY_pydriver_get_objects(icu->driver); - if (obarray) { - Object *ob, **oba = obarray; - - while (*oba) { - ob = *oba; - node1 = dag_get_node(dag, ob); - if (ob->type == OB_ARMATURE) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Python Ipo Driver"); - else - dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Python Ipo Driver"); - oba++; - } - - MEM_freeN(obarray); - } + for (fcu= adt->drivers.first; fcu; fcu= fcu->next) { + ChannelDriver *driver= fcu->driver; + DriverTarget *dtar; + + /* loop over targets, adding relationships as appropriate */ + for (dtar= driver->targets.first; dtar; dtar= dtar->next) { + if (dtar->id) { + if (GS(dtar->id->name)==ID_OB) { + Object *ob= (Object *)dtar->id; + + /* normal channel-drives-channel */ + node1 = dag_get_node(dag, dtar->id); + + /* check if bone... */ + if ((ob->type==OB_ARMATURE) && dtar->rna_path && strstr(dtar->rna_path, "pose.pose_channels[")) + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); + /* check if ob data */ + else if (dtar->rna_path && strstr(dtar->rna_path, "data.")) + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Driver"); + /* normal */ + else + dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Driver"); } -#endif /* DISABLE_PYTHON */ - } - else if (icu->driver->ob) { - node1 = dag_get_node(dag, icu->driver->ob); - if(icu->driver->blocktype==ID_AR) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Ipo Driver"); - else - dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver"); } } } } -static void dag_add_collision_field_relation(DagForest *dag, Object *ob, DagNode *node) +static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node) { Base *base; DagNode *node2; // would be nice to have a list of colliders here // so for now walk all objects in scene check 'same layer rule' - for(base = G.scene->base.first; base; base= base->next) { + for(base = scene->base.first; base; base= base->next) { if((base->lay & ob->lay) && base->object->pd) { Object *ob1= base->object; if((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) { @@ -368,10 +354,9 @@ static void dag_add_collision_field_relation(DagForest *dag, Object *ob, DagNode } } -static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int mask) +static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask) { bConstraint *con; - bConstraintChannel *conchan; DagNode * node; DagNode * node2; DagNode * node3; @@ -426,35 +411,11 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int } /* driver dependencies, nla modifiers */ - if(ob->ipo) - dag_add_driver_relation(ob->ipo, dag, node, 0); - - key= ob_get_key(ob); - if(key && key->ipo) - dag_add_driver_relation(key->ipo, dag, node, 1); - - for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) - if(conchan->ipo) - dag_add_driver_relation(conchan->ipo, dag, node, 0); - - if(ob->action) { - bActionChannel *chan; - for (chan = ob->action->chanbase.first; chan; chan=chan->next){ - if(chan->ipo) - dag_add_driver_relation(chan->ipo, dag, node, 1); - for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) - if(conchan->ipo) - dag_add_driver_relation(conchan->ipo, dag, node, 1); - } - } +#if 0 // XXX old animation system if(ob->nlastrips.first) { bActionStrip *strip; bActionChannel *chan; for(strip= ob->nlastrips.first; strip; strip= strip->next) { - if(strip->act && strip->act!=ob->action) - for (chan = strip->act->chanbase.first; chan; chan=chan->next) - if(chan->ipo) - dag_add_driver_relation(chan->ipo, dag, node, 1); if(strip->modifiers.first) { bActionModifier *amod; for(amod= strip->modifiers.first; amod; amod= amod->next) { @@ -466,13 +427,21 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int } } } +#endif // XXX old animation system + if (ob->adt) + dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation + + key= ob_get_key(ob); + if (key && key->adt) + dag_add_driver_relation(key->adt, dag, node, 1); + if (ob->modifiers.first) { ModifierData *md; for(md=ob->modifiers.first; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (mti->updateDepgraph) mti->updateDepgraph(md, dag, ob, node); + if (mti->updateDepgraph) mti->updateDepgraph(md, dag, scene, ob, node); } } if (ob->parent) { @@ -515,11 +484,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Proxy"); /* inverted relation, so addtoroot shouldn't be set to zero */ } + + if (ob->type==OB_CAMERA) { Camera *cam = (Camera *)ob->data; - if (cam->ipo) { - dag_add_driver_relation(cam->ipo, dag, node, 1); - } + if (cam->adt) + dag_add_driver_relation(cam->adt, dag, node, 1); if (cam->dof_ob) { node2 = dag_get_node(dag, cam->dof_ob); dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Camera DoF"); @@ -527,10 +497,10 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int } if (ob->type==OB_LAMP) { Lamp *la = (Lamp *)ob->data; - if (la->ipo) { - dag_add_driver_relation(la->ipo, dag, node, 1); - } + if (la->adt) + dag_add_driver_relation(la->adt, dag, node, 1); } + if (ob->transflag & OB_DUPLI) { if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { GroupObject *go; @@ -547,10 +517,10 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int /* softbody collision */ if((ob->type==OB_MESH) || (ob->type==OB_CURVE) || (ob->type==OB_LATTICE)) if(modifiers_isSoftbodyEnabled(ob) || modifiers_isClothEnabled(ob)) - dag_add_collision_field_relation(dag, ob, node); + dag_add_collision_field_relation(dag, scene, ob, node); if (ob->type==OB_MBALL) { - Object *mom= find_basis_mball(ob); + Object *mom= find_basis_mball(scene, ob); if(mom!=ob) { node2 = dag_get_node(dag, mom); dag_add_relation(dag,node,node2,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Metaball"); // mom depends on children! @@ -566,9 +536,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int node2 = dag_get_node(dag, cu->taperobj); dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper"); } - if(cu->ipo) - dag_add_driver_relation(cu->ipo, dag, node, 1); - + if (cu->adt) + dag_add_driver_relation(cu->adt, dag, node, 1); } else if(ob->type==OB_FONT) { Curve *cu= ob->data; @@ -613,7 +582,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int if(psys->effectors.first) psys_end_effectors(psys); - psys_init_effectors(ob,psys->part->eff_group,psys); + psys_init_effectors(scene, ob, psys->part->eff_group, psys); if(psys->effectors.first) { for(nec= psys->effectors.first; nec; nec= nec->next) { @@ -708,9 +677,9 @@ struct DagForest *build_dag(struct Scene *sce, short mask) for(base = sce->base.first; base; base= base->next) { ob= base->object; - build_dag_object(dag, scenenode, ob, mask); + build_dag_object(dag, scenenode, sce, ob, mask); if(ob->proxy) - build_dag_object(dag, scenenode, ob->proxy, mask); + build_dag_object(dag, scenenode, sce, ob->proxy, mask); /* handled in next loop */ if(ob->dup_group) @@ -721,7 +690,7 @@ struct DagForest *build_dag(struct Scene *sce, short mask) for(group= G.main->group.first; group; group= group->id.next) { if(group->id.flag & LIB_DOIT) { for(go= group->gobject.first; go; go= go->next) { - build_dag_object(dag, scenenode, go->ob, mask); + build_dag_object(dag, scenenode, sce, go->ob, mask); } group->id.flag &= ~LIB_DOIT; } @@ -1765,7 +1734,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) for(itA = node->child; itA; itA= itA->next) { all_layer |= itA->lay; /* the relationship is visible */ - if((itA->lay & layer) || (itA->node->ob == G.obedit)) { + if((itA->lay & layer)) { // XXX || (itA->node->ob == obedit) if(itA->node->type==ID_OB) { obc= itA->node->ob; oldflag= obc->recalc; @@ -1796,7 +1765,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) } } /* even nicer, we can clear recalc flags... */ - if((all_layer & layer)==0 && (ob != G.obedit)) { + if((all_layer & layer)==0) { // XXX && (ob != obedit)) { /* but existing displaylists or derivedmesh should be freed */ if(ob->recalc & OB_RECALC_DATA) object_free_display(ob); @@ -1810,7 +1779,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) /* could merge this in with loop above...? (ton) */ for(itA = node->child; itA; itA= itA->next) { /* the relationship is visible */ - if((itA->lay & layer) || (itA->node->ob == G.obedit)) { + if((itA->lay & layer)) { // XXX || (itA->node->ob == obedit) if(itA->node->type==ID_OB) { obc= itA->node->ob; /* child moves */ @@ -1953,25 +1922,28 @@ static int object_modifiers_use_time(Object *ob) return 0; } -static int exists_channel(Object *ob, char *name) +static short animdata_use_time(AnimData *adt) { - bActionStrip *strip; + NlaTrack *nlt; - if(ob->action) - if(get_action_channel(ob->action, name)) - return 1; + if(adt==NULL) return 0; + + /* check action - only if assigned, and it has anim curves */ + if (adt->action && adt->action->curves.first) + return 1; - for (strip=ob->nlastrips.first; strip; strip=strip->next) - if(get_action_channel(strip->act, name)) + /* check NLA tracks + strips */ + for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) { + if (nlt->strips.first) return 1; + } + return 0; } static void dag_object_time_update_flags(Object *ob) { - - if(ob->ipo) ob->recalc |= OB_RECALC_OB; - else if(ob->constraints.first) { + if(ob->constraints.first) { bConstraint *con; for (con = ob->constraints.first; con; con=con->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); @@ -2001,14 +1973,9 @@ static void dag_object_time_update_flags(Object *ob) if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } - if(ob->action || ob->nlastrips.first) { - /* since actions now are mixed, we set the recalcs on the safe side */ - ob->recalc |= OB_RECALC_OB; - if(ob->type==OB_ARMATURE) - ob->recalc |= OB_RECALC_DATA; - else if(exists_channel(ob, "Shape")) - ob->recalc |= OB_RECALC_DATA; - else if(ob->dup_group) { +#if 0 // XXX old animation system + if(ob->nlastrips.first) { + if(ob->dup_group) { bActionStrip *strip; /* this case is for groups with nla, whilst nla target has no action or nla */ for(strip= ob->nlastrips.first; strip; strip= strip->next) { @@ -2017,6 +1984,14 @@ static void dag_object_time_update_flags(Object *ob) } } } +#endif // XXX old animation system + + if(animdata_use_time(ob->adt)) { + ob->recalc |= OB_RECALC; + ob->adt->recalc |= ADT_RECALC_ANIM; + } + + if((ob->adt) && (ob->type==OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA; if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; @@ -2138,22 +2113,6 @@ void DAG_scene_update_flags(Scene *scene, unsigned int lay) } -/* for depgraph updating, all layers visible in a screen */ -/* this is a copy from editscreen.c... I need to think over a more proper solution for this */ -/* probably the DAG_object_flush_update() should give layer too? */ -/* or some kind of dag context... (DAG_set_layer) */ -static unsigned int dag_screen_view3d_layers(void) -{ - ScrArea *sa; - int layer= 0; - - for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { - if(sa->spacetype==SPACE_VIEW3D) - layer |= ((View3D *)sa->spacedata.first)->lay; - } - return layer; -} - /* flag this object and all its relations to recalc */ /* if you need to do more objects, tag object yourself and @@ -2187,9 +2146,9 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) } } - if(G.curscreen) - DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); - else +// XXX if(G.curscreen) +// DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); +// else DAG_scene_flush_update(sce, sce->lay, 0); } @@ -2308,6 +2267,7 @@ void DAG_pose_sort(Object *ob) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; +#if 0 // XXX old animation system... driver stuff to watch out for if(con->ipo) { IpoCurve *icu; for(icu= con->ipo->curve.first; icu; icu= icu->next) { @@ -2319,7 +2279,7 @@ void DAG_pose_sort(Object *ob) if(target) { node2 = dag_get_node(dag, target); dag_add_relation(dag, node2, node, 0, "Ipo Driver"); - + /* uncommented this line, results in dependencies * not being added properly for this constraint, * what is the purpose of this? - brecht */ @@ -2328,6 +2288,7 @@ void DAG_pose_sort(Object *ob) } } } +#endif // XXX old animation system... driver stuff to watch out for if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 7716d71225e..fe138407d54 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -60,7 +60,6 @@ #include "BLI_editVert.h" #include "BLI_edgehash.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_displist.h" @@ -305,22 +304,22 @@ int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, i /* create default shade input... save cpu cycles with ugly global */ /* XXXX bad code warning: local ShadeInput initialize... */ static ShadeInput shi; -static void init_fastshade_shadeinput(void) +static void init_fastshade_shadeinput(Render *re) { memset(&shi, 0, sizeof(ShadeInput)); - shi.lay= G.scene->lay; + shi.lay= RE_GetScene(re)->lay; shi.view[2]= -1.0f; shi.passflag= SCE_PASS_COMBINED; shi.combinedflag= -1; } -static Render *fastshade_get_render(void) +static Render *fastshade_get_render(Scene *scene) { Render *re= RE_GetRender("_Shade View_"); if(re==NULL) { re= RE_NewRender("_Shade View_"); - RE_Database_Baking(re, G.scene, 0, 0); /* 0= no faces */ + RE_Database_Baking(re, scene, 0, 0); /* 0= no faces */ } return re; } @@ -463,7 +462,7 @@ static void init_fastshade_for_ob(Render *re, Object *ob, int *need_orco_r, floa RE_shade_external(re, NULL, NULL); /* initialize global here */ - init_fastshade_shadeinput(); + init_fastshade_shadeinput(re); RE_DataBase_GetView(re, tmat); Mat4MulMat4(mat, ob->obmat, tmat); @@ -516,9 +515,9 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un dataMask |= CD_MASK_ORCO; if (onlyForMesh) - dm = mesh_get_derived_deform(ob, dataMask); + dm = mesh_get_derived_deform(RE_GetScene(re), ob, dataMask); else - dm = mesh_get_derived_final(ob, dataMask); + dm = mesh_get_derived_final(RE_GetScene(re), ob, dataMask); mvert = dm->getVertArray(dm); mface = dm->getFaceArray(dm); @@ -558,6 +557,7 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un } for (i=0; i<totface; i++) { + extern Material defmaterial; /* material.c */ MFace *mf= &mface[i]; Material *ma= give_current_material(ob, mf->mat_nr+1); int j, vidx[4], nverts= mf->v4?4:3; @@ -609,13 +609,13 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un end_fastshade_for_ob(ob); } -void shadeMeshMCol(Object *ob, Mesh *me) +void shadeMeshMCol(Scene *scene, Object *ob, Mesh *me) { int a; char *cp; unsigned int *mcol= (unsigned int*)me->mcol; - Render *re= fastshade_get_render(); + Render *re= fastshade_get_render(scene); mesh_create_shadedColors(re, ob, 1, &mcol, NULL); me->mcol= (MCol*)mcol; @@ -628,7 +628,7 @@ void shadeMeshMCol(Object *ob, Mesh *me) /* has base pointer, to check for layer */ /* called from drawobject.c */ -void shadeDispList(Base *base) +void shadeDispList(Scene *scene, Base *base) { Object *ob= base->object; DispList *dl, *dlob; @@ -640,7 +640,7 @@ void shadeDispList(Base *base) unsigned int *col1; int a, need_orco; - re= fastshade_get_render(); + re= fastshade_get_render(scene); dl = find_displist(&ob->disp, DL_VERTCOL); if (dl) { @@ -662,13 +662,15 @@ void shadeDispList(Base *base) init_fastshade_for_ob(re, ob, &need_orco, mat, imat); - if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { + if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { /* now we need the normals */ cu= ob->data; dl= cu->disp.first; while(dl) { + extern Material defmaterial; /* material.c */ + dlob= MEM_callocN(sizeof(DispList), "displistshade"); BLI_addtail(&ob->disp, dlob); dlob->type= DL_VERTCOL; @@ -739,6 +741,7 @@ void shadeDispList(Base *base) if(dl->type==DL_INDEX4) { if(dl->nors) { + extern Material defmaterial; /* material.c */ if(dl->col1) MEM_freeN(dl->col1); col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1"); @@ -776,22 +779,22 @@ void shadeDispList(Base *base) /* frees render and shade part of displists */ /* note: dont do a shade again, until a redraw happens */ -void reshadeall_displist(void) +void reshadeall_displist(Scene *scene) { Base *base; Object *ob; fastshade_free_render(); - for(base= G.scene->base.first; base; base= base->next) { + for(base= scene->base.first; base; base= base->next) { ob= base->object; if(ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) freedisplist(&ob->disp); - if(base->lay & G.scene->lay) { + if(base->lay & scene->lay) { /* Metaballs have standard displist at the Object */ - if(ob->type==OB_MBALL) shadeDispList(base); + if(ob->type==OB_MBALL) shadeDispList(scene, base); } } } @@ -937,7 +940,7 @@ void filldisplist(ListBase *dispbase, ListBase *to) DispList *dlnew=0, *dl; float *f1; int colnr=0, charidx=0, cont=1, tot, a, *index; - long totvert; + intptr_t totvert; if(dispbase==0) return; if(dispbase->first==0) return; @@ -982,7 +985,7 @@ void filldisplist(ListBase *dispbase, ListBase *to) dl= dl->next; } - if(totvert && BLI_edgefill(0, (G.obedit && G.obedit->actcol)?(G.obedit->actcol-1):0)) { + if(totvert && BLI_edgefill(0, 0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { /* count faces */ tot= 0; @@ -1127,7 +1130,7 @@ void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase) - first point left, last point right - based on subdivided points in original curve, not on points in taper curve (still) */ -float calc_taper(Object *taperobj, int cur, int tot) +float calc_taper(Scene *scene, Object *taperobj, int cur, int tot) { Curve *cu; DispList *dl; @@ -1137,7 +1140,7 @@ float calc_taper(Object *taperobj, int cur, int tot) cu= taperobj->data; dl= cu->disp.first; if(dl==NULL) { - makeDispListCurveTypes(taperobj, 0); + makeDispListCurveTypes(scene, taperobj, 0); dl= cu->disp.first; } if(dl) { @@ -1170,15 +1173,15 @@ float calc_taper(Object *taperobj, int cur, int tot) return 1.0; } -void makeDispListMBall(Object *ob) +void makeDispListMBall(Scene *scene, Object *ob) { if(!ob || ob->type!=OB_MBALL) return; freedisplist(&(ob->disp)); if(ob->type==OB_MBALL) { - if(ob==find_basis_mball(ob)) { - metaball_polygonize(ob); + if(ob==find_basis_mball(scene, ob)) { + metaball_polygonize(scene, ob); tex_space_mball(ob); object_deform_mball(ob); @@ -1214,12 +1217,14 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed return preTesselatePoint; } -void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r) +static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r) { - int editmode = (!forRender && ob==G.obedit); ModifierData *md = modifiers_getVirtualModifierList(ob); - ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + ModifierData *preTesselatePoint; + Curve *cu= ob->data; + ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb; int numVerts = 0; + int editmode = (!forRender && cu->editnurb); float (*originalVerts)[3] = NULL; float (*deformedVerts)[3] = NULL; int required_mode; @@ -1227,9 +1232,11 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float ( if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; + preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + if(editmode) required_mode |= eModifierMode_Editmode; - if(ob!=G.obedit && do_ob_key(ob)) { + if(cu->editnurb==NULL && do_ob_key(scene, ob)) { deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts); originalVerts = MEM_dupallocN(deformedVerts); } @@ -1238,6 +1245,8 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float ( for (; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if ((md->mode & required_mode) != required_mode) continue; if (mti->isDisabled && mti->isDisabled(md)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; @@ -1247,7 +1256,7 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float ( originalVerts = MEM_dupallocN(deformedVerts); } - mti->deformVerts(md, ob, NULL, deformedVerts, numVerts); + mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, forRender, editmode); if (md==preTesselatePoint) break; @@ -1263,17 +1272,21 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float ( *numVerts_r = numVerts; } -static void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3]) +static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3]) { - int editmode = (!forRender && ob==G.obedit); ModifierData *md = modifiers_getVirtualModifierList(ob); - ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + ModifierData *preTesselatePoint; + Curve *cu= ob->data; + ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb; DispList *dl; int required_mode; + int editmode = (!forRender && cu->editnurb); if(forRender) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; + preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode); + if(editmode) required_mode |= eModifierMode_Editmode; if (preTesselatePoint) { @@ -1283,6 +1296,8 @@ static void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *disp for (; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if ((md->mode & required_mode) != required_mode) continue; if (mti->isDisabled && mti->isDisabled(md)) continue; if (mti->type!=eModifierTypeType_OnlyDeform && mti->type!=eModifierTypeType_DeformOrConstruct) continue; @@ -1302,7 +1317,7 @@ static void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *disp fp+= offs; } - mti->deformVerts(md, ob, NULL, (float(*)[3]) allverts, totvert); + mti->deformVerts(md, ob, NULL, (float(*)[3]) allverts, totvert, forRender, editmode); fp= allverts; for (dl=dispbase->first; dl; dl=dl->next) { @@ -1314,7 +1329,7 @@ static void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *disp } else { for (dl=dispbase->first; dl; dl=dl->next) { - mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr); + mti->deformVerts(md, ob, NULL, (float(*)[3]) dl->verts, (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr, forRender, editmode); } } } @@ -1356,7 +1371,7 @@ static void displist_surf_indices(DispList *dl) } -void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) +void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase, int forRender) { ListBase *nubase; Nurb *nu; @@ -1368,14 +1383,12 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) float (*originalVerts)[3]; float (*deformedVerts)[3]; - if(!forRender && ob==G.obedit) { - nubase= &editNurb; - } - else { + if(!forRender && cu->editnurb) + nubase= cu->editnurb; + else nubase= &cu->nurb; - } - curve_calc_modifiers_pre(ob, nubase, forRender, &originalVerts, &deformedVerts, &numVerts); + curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts); for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { @@ -1429,10 +1442,10 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) tex_space_curve(cu); } - curve_calc_modifiers_post(ob, nubase, dispbase, forRender, originalVerts, deformedVerts); + curve_calc_modifiers_post(scene, ob, dispbase, forRender, originalVerts, deformedVerts); } -void makeDispListCurveTypes(Object *ob, int forOrco) +void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco) { Curve *cu = ob->data; ListBase *dispbase; @@ -1445,29 +1458,33 @@ void makeDispListCurveTypes(Object *ob, int forOrco) freedisplist(dispbase); if(ob->type==OB_SURF) { - makeDispListSurf(ob, dispbase, 0); + makeDispListSurf(scene, ob, dispbase, 0); } - else if ELEM(ob->type, OB_CURVE, OB_FONT) { + else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; + ListBase *nubase; float (*originalVerts)[3]; float (*deformedVerts)[3]; - int obedit= (G.obedit && G.obedit->data==ob->data && G.obedit->type==OB_CURVE); - ListBase *nubase = obedit?&editNurb:&cu->nurb; int numVerts; + if(cu->editnurb) + nubase= cu->editnurb; + else + nubase= &cu->nurb; + BLI_freelistN(&(cu->bev)); if(cu->path) free_path(cu->path); cu->path= NULL; - if(ob->type==OB_FONT) text_to_curve(ob, 0); + if(ob->type==OB_FONT) BKE_text_to_curve(scene, ob, 0); - if(!forOrco) curve_calc_modifiers_pre(ob, nubase, 0, &originalVerts, &deformedVerts, &numVerts); + if(!forOrco) curve_calc_modifiers_pre(scene, ob, 0, &originalVerts, &deformedVerts, &numVerts); makeBevelList(ob); /* If curve has no bevel will return nothing */ - makebevelcurve(ob, &dlbev); + makebevelcurve(scene, ob, &dlbev); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width==1.0f) { @@ -1545,7 +1562,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) fac = bevp->radius; } else { - fac = calc_taper(cu->taperobj, a, bl->nr); + fac = calc_taper(scene, cu->taperobj, a, bl->nr); } if (bevp->f1) { @@ -1590,7 +1607,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) if(cu->flag & CU_PATH) calc_curvepath(ob); - if(!forOrco) curve_calc_modifiers_post(ob, nubase, &cu->disp, 0, originalVerts, deformedVerts); + if(!forOrco) curve_calc_modifiers_post(scene, ob, &cu->disp, 0, originalVerts, deformedVerts); tex_space_curve(cu); } diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index cca5d68167e..9858025af5a 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -57,7 +57,6 @@ #include "BKE_action.h" #include "BKE_anim.h" /* needed for where_on_path */ #include "BKE_armature.h" -#include "BKE_bad_level_calls.h" #include "BKE_blender.h" #include "BKE_collision.h" #include "BKE_constraint.h" @@ -80,19 +79,20 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" -#include "PIL_time.h" #include "RE_render_ext.h" /* fluid sim particle import */ #ifndef DISABLE_ELBEEM #include "DNA_object_fluidsim.h" #include "LBM_fluidsim.h" -#include "elbeem.h" #include <zlib.h> #include <string.h> #endif // DISABLE_ELBEEM +//XXX #include "BIF_screen.h" + /* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */ + typedef struct VeNoCo { float co[3], no[3]; } VeNoCo; @@ -138,7 +138,7 @@ void free_effects(ListBase *lb) /* -------------------------- Effectors ------------------ */ -static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) +static void add_to_effectorcache(ListBase *lb, Scene *scene, Object *ob, Object *obsrc) { pEffectorCache *ec; PartDeflect *pd= ob->pd; @@ -148,7 +148,7 @@ static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) Curve *cu= ob->data; if(cu->flag & CU_PATH) { if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(ob, 0); + makeDispListCurveTypes(scene, ob, 0); if(cu->path && cu->path->data) { ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); ec->ob= ob; @@ -161,8 +161,7 @@ static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) if(pd->forcefield == PFIELD_WIND) { - pd->rng = rng_new(1); - rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + pd->rng = rng_new(pd->seed); } ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); @@ -172,7 +171,7 @@ static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) } /* returns ListBase handle with objects taking part in the effecting */ -ListBase *pdInitEffectors(Object *obsrc, Group *group) +ListBase *pdInitEffectors(Scene *scene, Object *obsrc, Group *group) { static ListBase listb={NULL, NULL}; pEffectorCache *ec; @@ -184,14 +183,14 @@ ListBase *pdInitEffectors(Object *obsrc, Group *group) for(go= group->gobject.first; go; go= go->next) { if( (go->ob->lay & layer) && go->ob->pd && go->ob!=obsrc) { - add_to_effectorcache(&listb, go->ob, obsrc); + add_to_effectorcache(&listb, scene, go->ob, obsrc); } } } else { - for(base = G.scene->base.first; base; base= base->next) { + for(base = scene->base.first; base; base= base->next) { if( (base->lay & layer) && base->object->pd && base->object!=obsrc) { - add_to_effectorcache(&listb, base->object, obsrc); + add_to_effectorcache(&listb, scene, base->object, obsrc); } } } @@ -238,14 +237,14 @@ static void eff_tri_ray_hit(void *userdata, int index, const BVHTreeRay *ray, BV } // get visibility of a wind ray -static float eff_calc_visibility(Object *ob, float *co, float *dir) +static float eff_calc_visibility(Scene *scene, Object *ob, float *co, float *dir) { CollisionModifierData **collobjs = NULL; int numcollobj = 0, i; float norm[3], len = 0.0; float visibility = 1.0; - collobjs = get_collisionobjects(ob, &numcollobj); + collobjs = get_collisionobjects(scene, ob, &numcollobj); if(!collobjs) return 0; @@ -286,14 +285,14 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) // noise function for wind e.g. static float wind_func(struct RNG *rng, float strength) { - int random = (rng_getInt(rng)+1) % 65535; // max 2357 + int random = (rng_getInt(rng)+1) % 128; // max 2357 float force = rng_getFloat(rng) + 1.0f; float ret; float sign = 0; - sign = (random > 32000.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution + sign = ((float)random > 64.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution - ret = sign*((float)random / force)*strength/65535.0f; + ret = sign*((float)random / force)*strength/128.0f; return ret; } @@ -370,7 +369,7 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part) return falloff; } -void do_physical_effector(Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size) +void do_physical_effector(Scene *scene, Object *ob, float *opco, short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise_factor, float charge, float pa_size) { float mag_vec[3]={0,0,0}; float temp[3], temp2[3]; @@ -378,7 +377,7 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, float noise = 0, visibility; // calculate visibility - visibility = eff_calc_visibility(ob, opco, vec_to_part); + visibility = eff_calc_visibility(scene, ob, opco, vec_to_part); if(visibility <= 0.0) return; falloff *= visibility; @@ -492,6 +491,7 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, /* -------- pdDoEffectors() -------- generic force/speed system, now used for particles and softbodies + scene = scene where it runs in, for time and stuff lb = listbase with objects that take part in effecting opco = global coord, as input force = force accumulator @@ -503,7 +503,7 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, guide = old speed of particle */ -void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags) +void pdDoEffectors(Scene *scene, ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags) { /* Modifies the force on a particle according to its @@ -534,7 +534,7 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float pd= ob->pd; /* Get IPO force strength and fall off values here */ - where_is_object_time(ob,cur_time); + where_is_object_time(scene, ob, cur_time); /* use center of object for distance calculus */ VecSubf(vec_to_part, opco, ob->obmat[3]); @@ -547,9 +547,9 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float else { float field[3]={0,0,0}, tmp[3]; VECCOPY(field, force); - do_physical_effector(ob, opco, pd->forcefield,pd->f_strength,distance, - falloff,pd->f_dist,pd->f_damp,ob->obmat[2],vec_to_part, - speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f); + do_physical_effector(scene, ob, opco, pd->forcefield,pd->f_strength,distance, + falloff, pd->f_dist, pd->f_damp, ob->obmat[2], vec_to_part, + speed,force, pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f); // for softbody backward compatibility if(flags & PE_WIND_AS_SPEED){ diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index ee3fd59fe9f..929d3f942dc 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -19,13 +19,14 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. * * Contributor(s): * - Martin DeMello * Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline * Copyright (C) 2004 by Etheract Software Labs * + * - Blender Foundation + * * ***** END GPL LICENSE BLOCK ***** * * eigen videoscape formaat: @@ -100,12 +101,12 @@ #include "DNA_view3d_types.h" #include "DNA_userdef_types.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BKE_blender.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -114,6 +115,7 @@ #include "BKE_object.h" #include "BKE_material.h" #include "BKE_exotic.h" + /* #include "BKE_error.h" */ #include "BKE_screen.h" #include "BKE_displist.h" @@ -125,12 +127,10 @@ #include "BPY_extern.h" #endif -#include "blendef.h" - #include "zlib.h" static int is_dxf(char *str); -static void dxf_read(char *filename); +static void dxf_read(Scene *scene, char *filename); static int is_stl(char *str); static int is_stl_ascii(char *str) @@ -181,11 +181,10 @@ static int is_stl(char *str) MEM_freeN(facedata); \ fclose(fpSTL); \ sprintf(error_msg, "Problems reading face %d!", i); \ - error(error_msg); \ return; \ } \ else { \ - if (G.order==B_ENDIAN) { \ + if (ENDIAN_ORDER==B_ENDIAN) { \ SWITCH_INT(mvert->co[0]); \ SWITCH_INT(mvert->co[1]); \ SWITCH_INT(mvert->co[2]); \ @@ -235,7 +234,7 @@ static void mesh_add_normals_flags(Mesh *me) } } -static void read_stl_mesh_binary(char *str) +static void read_stl_mesh_binary(Scene *scene, char *str) { FILE *fpSTL; Object *ob; @@ -248,13 +247,13 @@ static void read_stl_mesh_binary(char *str) fpSTL= fopen(str, "rb"); if(fpSTL==NULL) { - error("Can't read file"); + //XXX error("Can't read file"); return; } fseek(fpSTL, 80, SEEK_SET); fread(&numfacets, 4*sizeof(char), 1, fpSTL); - if (G.order==B_ENDIAN) { + if (ENDIAN_ORDER==B_ENDIAN) { SWITCH_INT(numfacets); } @@ -297,7 +296,7 @@ static void read_stl_mesh_binary(char *str) fseek(fpSTL, 2, SEEK_CUR); } - ob= add_object(OB_MESH); + ob= add_object(scene, OB_MESH); me= ob->data; me->totvert = totvert; me->totface = totface; @@ -309,7 +308,7 @@ static void read_stl_mesh_binary(char *str) mesh_add_normals_flags(me); make_edges(me, 0); } - waitcursor(1); + //XXX waitcursor(1); } fclose(fpSTL); @@ -321,7 +320,6 @@ static void read_stl_mesh_binary(char *str) fclose(fpSTL); \ sprintf(error_msg, "Can't allocate storage for %d faces!", \ numtenthousand * 10000); \ - error(error_msg); \ return; \ } @@ -330,7 +328,6 @@ static void read_stl_mesh_binary(char *str) fclose(fpSTL); \ free(vertdata); \ sprintf(error_msg, "Line %d: %s", linenum, message); \ - error(message); \ return; \ } @@ -348,7 +345,7 @@ static void read_stl_mesh_binary(char *str) STLBAILOUT("Bad vertex!"); \ ++totvert; \ } -static void read_stl_mesh_ascii(char *str) +static void read_stl_mesh_ascii(Scene *scene, char *str) { FILE *fpSTL; char buffer[2048], *cp; @@ -366,7 +363,7 @@ static void read_stl_mesh_ascii(char *str) fpSTL= fopen(str, "r"); if(fpSTL==NULL) { - error("Can't read file"); + //XXX error("Can't read file"); return; } @@ -376,7 +373,7 @@ static void read_stl_mesh_ascii(char *str) */ numtenthousand = 1; vertdata = malloc(numtenthousand*3*30000*sizeof(float)); // uses realloc! - if (!vertdata) STLALLOCERROR; + if (!vertdata); STLALLOCERROR; linenum = 1; /* Get rid of the first line */ @@ -399,7 +396,7 @@ static void read_stl_mesh_ascii(char *str) ++numtenthousand; vertdata = realloc(vertdata, numtenthousand*3*30000*sizeof(float)); - if (!vertdata) STLALLOCERROR; + if (!vertdata); STLALLOCERROR; } /* Don't read normal, but check line for proper syntax anyway @@ -440,7 +437,7 @@ static void read_stl_mesh_ascii(char *str) fclose(fpSTL); /* OK, lets create our mesh */ - ob = add_object(OB_MESH); + ob = add_object(scene, OB_MESH); me = ob->data; me->totface = totface; @@ -477,7 +474,7 @@ static void read_stl_mesh_ascii(char *str) mesh_add_normals_flags(me); make_edges(me, 0); - waitcursor(1); + //XXX waitcursor(1); } #undef STLALLOCERROR @@ -485,7 +482,7 @@ static void read_stl_mesh_ascii(char *str) #undef STLREADLINE #undef STLREADVERT -static void read_videoscape_mesh(char *str) +static void read_videoscape_mesh(Scene *scene, char *str) { Object *ob; Mesh *me; @@ -501,7 +498,7 @@ static void read_videoscape_mesh(char *str) fp= fopen(str, "rb"); if(fp==NULL) { - error("Can't read file"); + //XXX error("Can't read file"); return; } @@ -510,12 +507,12 @@ static void read_videoscape_mesh(char *str) fscanf(fp, "%d\n", &verts); if(verts<=0) { fclose(fp); - error("Read error"); + //XXX error("Read error"); return; } if(verts>MESH_MAX_VERTS) { - error("too many vertices"); + //XXX error("too many vertices"); fclose(fp); return; } @@ -559,7 +556,7 @@ static void read_videoscape_mesh(char *str) } /* new object */ - ob= add_object(OB_MESH); + ob= add_object(scene, OB_MESH); me= ob->data; me->totvert= verts; me->totface= totedge+tottria+totquad; @@ -689,194 +686,10 @@ static void read_videoscape_mesh(char *str) mesh_add_normals_flags(me); make_edges(me, 0); - waitcursor(1); -} - -static void read_radiogour(char *str) -{ - Object *ob; - Mesh *me; - MVert *mvert; - MFace *mface; - FILE *fp; - float *vertdata, *vd, min[3], max[3], cent[3], ftemp; - unsigned int *colv, *colf, *colvertdata; - int itemp, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first; - int end; - char s[50]; - - fp= fopen(str, "rb"); - if(fp==NULL) { - error("Can't read file"); - return; - } - - fscanf(fp, "%40s", s); - - fscanf(fp, "%d\n", &verts); - if(verts<=0) { - fclose(fp); - error("Read error"); - return; - } - - if(verts>MESH_MAX_VERTS) { - error("too many vertices"); - fclose(fp); - return; - } - - INIT_MINMAX(min, max); - vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer"); - colv= colvertdata= MEM_mallocN(verts*sizeof(float), "coldata"); - - for(a=0; a<verts; a++) { - fscanf(fp, "%f %f %f %i", vd, vd+1, vd+2, colv); - DO_MINMAX(vd, min, max); - vd+=3; - colv++; - } - - /* count faces */ - end= 1; - while(end>0) { - end= fscanf(fp,"%d", &poly); - if(end<=0) break; - - if(poly==3) tottria++; - else if(poly==4) totquad++; - else totedge+= poly; - - for(a=0;a<poly;a++) { - end= fscanf(fp,"%d", &nr); - if(end<=0) break; - } - if(end<=0) break; - - } - - if(totedge+tottria+totquad>MESH_MAX_VERTS) { - printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad); - error("too many faces"); - MEM_freeN(vertdata); - MEM_freeN(colvertdata); - fclose(fp); - return; - } - - /* new object */ - ob= add_object(OB_MESH); - me= ob->data; - me->totvert= verts; - me->totface= totedge+tottria+totquad; - me->flag= 0; - - me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, - NULL, me->totvert); - me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, - NULL, me->totface); - - /* verts */ - - cent[0]= (min[0]+max[0])/2.0f; - cent[1]= (min[1]+max[1])/2.0f; - cent[2]= (min[2]+max[2])/2.0f; - VECCOPY(ob->loc, cent); - - a= me->totvert; - vd= vertdata; - mvert= me->mvert; - while(a--) { - VecSubf(mvert->co, vd, cent); - mvert++; - vd+= 3; - } - - /* faces */ - if(me->totface) { - rewind(fp); - - fscanf(fp, "%40s", s); - fscanf(fp, "%d\n", &verts); - for(a=0;a<verts;a++) { - fscanf(fp, "%f %f %f %i", &ftemp, &ftemp, &ftemp, &itemp); - } - - a= me->totface; - mface= me->mface; - while(a--) { - end= fscanf(fp,"%d", &poly); - if(end<=0) break; - - if(poly==3 || poly==4) { - fscanf(fp,"%d", &nr); - mface->v1= MIN2(nr, me->totvert-1); - fscanf(fp,"%d", &nr); - mface->v2= MIN2(nr, me->totvert-1); - fscanf(fp,"%d", &nr); - mface->v3= MIN2(nr, me->totvert-1); - if(poly==4) { - if( fscanf(fp,"%d", &nr) <=0 ) break; - mface->v4= MIN2(nr, me->totvert-1); - } - - test_index_face(mface, NULL, 0, poly); - - mface++; - } - else { - if( fscanf(fp,"%d", &nr0) <=0) break; - first= nr0; - for(b=1; b<poly; b++) { - end= fscanf(fp,"%d", &nr); - if(end<=0) break; - nr= MIN2(nr, me->totvert-1); - mface->v1= nr; - mface->v2= nr0; - nr0= nr; - mface++; - a--; - } - mface->v1= first; - mface->v2= nr; - mface->flag= ME_SMOOTH; - - mface++; - if(end<=0) break; - } - } - - /* mcol is 4 colors per face */ - me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "mcol"); - colf= (unsigned int *)me->mcol; - - a= me->totface; - mface= me->mface; - while(a--) { - - colf[0]= colvertdata[mface->v1]; - colf[1]= colvertdata[mface->v2]; - colf[2]= colvertdata[mface->v3]; - colf[3]= colvertdata[mface->v4]; - - colf+= 4; - mface++; - } - - MEM_freeN(colvertdata); - } - - fclose(fp); - MEM_freeN(vertdata); - - mesh_add_normals_flags(me); - make_edges(me, 0); - - waitcursor(1); + //XXX waitcursor(1); } - -static void read_videoscape_lamp(char *str) +static void read_videoscape_lamp(Scene *scene, char *str) { Object *ob; Lamp *la; @@ -887,7 +700,7 @@ static void read_videoscape_lamp(char *str) fp= fopen(str, "rb"); if(fp==NULL) { - error("Can't read file"); + //XXX error("Can't read file"); return; } @@ -895,7 +708,7 @@ static void read_videoscape_lamp(char *str) fscanf(fp, "%d\n", &tot); while(tot--) { - ob= add_object(OB_LAMP); + ob= add_object(scene, OB_LAMP); la= ob->data; fscanf(fp, "%d\n", &val); @@ -918,7 +731,7 @@ static void read_videoscape_lamp(char *str) fclose(fp); } -static void read_videoscape_nurbs(char *str) +static void read_videoscape_nurbs(Scene *scene, char *str) { Object *ob; Curve *cu; @@ -932,15 +745,15 @@ static void read_videoscape_nurbs(char *str) fp= fopen(str, "rb"); if(fp==NULL) { - error("Can't read file"); + //XXX error("Can't read file"); return; } fscanf(fp, "%40s", s); fscanf(fp, "%d\n", &type); - if(type==5) ob= add_object(OB_SURF); - else ob= add_object(OB_CURVE); + if(type==5) ob= add_object(scene, OB_SURF); + else ob= add_object(scene, OB_CURVE); cu= ob->data; fscanf(fp, "%d\n", &tot); @@ -1020,7 +833,7 @@ static void read_videoscape_nurbs(char *str) fclose(fp); } -static void read_videoscape(char *str) +static void read_videoscape(Scene *scene, char *str) { int file, type; unsigned int val; @@ -1036,9 +849,9 @@ static void read_videoscape(char *str) read(file, &type, 4); close(file); - if(type==DDG1) read_videoscape_mesh(name); - else if(type==DDG2) read_videoscape_lamp(name); - else if(type==DDG3) read_videoscape_nurbs(name); + if(type==DDG1) read_videoscape_mesh(scene, name); + else if(type==DDG2) read_videoscape_lamp(scene, name); + else if(type==DDG3) read_videoscape_nurbs(scene, name); } val = BLI_stringdec(name, head, tail, &numlen); @@ -1131,7 +944,7 @@ static int iv_finddata(struct IvNode *iv, char *field, int fieldnr) float *fp; int len, stackcount, skipdata=0; char *cpa, terminator, str[64]; - long i; + intptr_t i; len= strlen(field); @@ -1231,7 +1044,7 @@ static void read_iv_index(float *data, float *baseadr, float *index, int nr, int -static void read_inventor(char *str, struct ListBase *listb) +static void read_inventor(Scene *scene, char *str, struct ListBase *listb) { struct IvNode *iv, *ivp, *ivn; char *maindata, *md, *cpa; @@ -1246,7 +1059,7 @@ static void read_inventor(char *str, struct ListBase *listb) file= open(str, O_BINARY|O_RDONLY); if(file== -1) { - error("Can't read file\n"); + //XXX error("Can't read file\n"); return; } @@ -1829,7 +1642,7 @@ static void read_inventor(char *str, struct ListBase *listb) BPoint *bp; if(ivsurf==0) { - ob= add_object(OB_SURF); + ob= add_object(scene, OB_SURF); ivsurf= ob; } else ob= ivsurf; @@ -1912,7 +1725,7 @@ static void read_inventor(char *str, struct ListBase *listb) /* ************************************************************ */ -static void displist_to_mesh(DispList *dlfirst) +static void displist_to_mesh(Scene *scene, DispList *dlfirst) { Object *ob; Mesh *me; @@ -2021,7 +1834,7 @@ static void displist_to_mesh(DispList *dlfirst) } if(totcol>16) { - error("Found more than 16 different colors"); + //XXX error("Found more than 16 different colors"); totcol= 16; } @@ -2029,9 +1842,9 @@ static void displist_to_mesh(DispList *dlfirst) vec[1]= (min[1]+max[1])/2; vec[2]= (min[2]+max[2])/2; - ob= add_object(OB_MESH); + ob= add_object(scene, OB_MESH); VECCOPY(ob->loc, vec); - where_is_object(ob); + where_is_object(scene, ob); me= ob->data; @@ -2251,7 +2064,7 @@ static void displist_to_mesh(DispList *dlfirst) make_edges(me, 0); } -static void displist_to_objects(ListBase *lbase) +static void displist_to_objects(Scene *scene, ListBase *lbase) { DispList *dl, *first, *prev, *next; ListBase tempbase; @@ -2259,8 +2072,8 @@ static void displist_to_objects(ListBase *lbase) /* irst this: is still active */ if(ivsurf) { - where_is_object(ivsurf); - docenter_new(); + where_is_object(scene, ivsurf); +// XXX docenter_new(); } dl= lbase->first; @@ -2296,7 +2109,7 @@ static void displist_to_objects(ListBase *lbase) if(totvert==0) { - if(ivsurf==0) error("Found no data"); + if(ivsurf==0) ; //XXX error("Found no data"); if(lbase->first) BLI_freelistN(lbase); return; @@ -2340,12 +2153,12 @@ static void displist_to_objects(ListBase *lbase) totvert+= vert; if(totvert > maxaantal || dl->next==0) { if(dl->next==0) { - displist_to_mesh(first); + displist_to_mesh(scene, first); } else if(dl->prev) { prev= dl->prev; prev->next= 0; - displist_to_mesh(first); + displist_to_mesh(scene, first); prev->next= dl; first= dl; totvert= 0; @@ -2360,13 +2173,13 @@ static void displist_to_objects(ListBase *lbase) curcol++; } } - else displist_to_mesh(lbase->first); + else displist_to_mesh(scene, lbase->first); freedisplist(lbase); } -int BKE_read_exotic(char *name) +int BKE_read_exotic(Scene *scene, char *name) { ListBase lbase={0, 0}; int len; @@ -2382,7 +2195,7 @@ int BKE_read_exotic(char *name) gzfile = gzopen(name,"rb"); if (NULL == gzfile ) { - error("Can't open file: %s", name); + //XXX error("Can't open file: %s", name); retval= -1; } else { gzread(gzfile, str, 31); @@ -2390,47 +2203,39 @@ int BKE_read_exotic(char *name) if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0) && !BLI_testextensie(name,".blend.gz")) { - waitcursor(1); + //XXX waitcursor(1); - if(*s0==GOUR) { - if(G.obedit) { - error("Unable to perform function in EditMode"); + if(ELEM4(*s0, DDG1, DDG2, DDG3, DDG4)) { + if(0) { // XXX obedit) { + //XXX error("Unable to perform function in EditMode"); } else { - read_radiogour(name); - retval = 1; - } - } - else if ELEM4(*s0, DDG1, DDG2, DDG3, DDG4) { - if(G.obedit) { - error("Unable to perform function in EditMode"); - } else { - read_videoscape(name); + read_videoscape(scene, name); retval = 1; } } else if(strncmp(str, "#Inventor V1.0", 14)==0) { if( strncmp(str+15, "ascii", 5)==0) { - read_inventor(name, &lbase); - displist_to_objects(&lbase); + read_inventor(scene, name, &lbase); + displist_to_objects(scene, &lbase); retval = 1; } else { - error("Can only read Inventor 1.0 ascii"); + //XXX error("Can only read Inventor 1.0 ascii"); } } else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) { - read_inventor(name, &lbase); - displist_to_objects(&lbase); + read_inventor(scene, name, &lbase); + displist_to_objects(scene, &lbase); retval = 1; } else if(is_dxf(name)) { - dxf_read(name); + dxf_read(scene, name); retval = 1; } else if(is_stl(name)) { if (is_stl_ascii(name)) - read_stl_mesh_ascii(name); + read_stl_mesh_ascii(scene, name); else - read_stl_mesh_binary(name); + read_stl_mesh_binary(scene, name); retval = 1; } #ifndef DISABLE_PYTHON @@ -2439,12 +2244,12 @@ int BKE_read_exotic(char *name) if (BPY_call_importloader(name)) { retval = 1; } else { - error("Unknown file type or error, check console"); + //XXX error("Unknown file type or error, check console"); } } #endif /* DISABLE_PYTHON */ - waitcursor(0); + //XXX waitcursor(0); } } } @@ -2465,7 +2270,7 @@ static void write_vert_stl(Object *ob, MVert *verts, int index, FILE *fpSTL) VECCOPY(vert, verts[(index)].co); Mat4MulVecfl(ob->obmat, vert); - if (G.order==B_ENDIAN) { + if (ENDIAN_ORDER==B_ENDIAN) { SWITCH_INT(vert[0]); SWITCH_INT(vert[1]); SWITCH_INT(vert[2]); @@ -2502,10 +2307,10 @@ static int write_derivedmesh_stl(FILE *fpSTL, Object *ob, DerivedMesh *dm) return numfacets; } -static int write_object_stl(FILE *fpSTL, Object *ob, Mesh *me) +static int write_object_stl(FILE *fpSTL, Scene *scene, Object *ob, Mesh *me) { int numfacets = 0; - DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); numfacets += write_derivedmesh_stl(fpSTL, ob, dm); @@ -2514,7 +2319,7 @@ static int write_object_stl(FILE *fpSTL, Object *ob, Mesh *me) return numfacets; } -void write_stl(char *str) +void write_stl(Scene *scene, char *str) { Object *ob; Mesh *me; @@ -2528,19 +2333,19 @@ void write_stl(char *str) if (!during_script()) { if (BLI_exists(str)) - if(saveover(str)==0) - return; + ; //XXX if(saveover(str)==0) + //XXX return; } fpSTL= fopen(str, "wb"); if(fpSTL==NULL) { - if (!during_script()) error("Can't write file"); + if (!during_script()) ; //XXX error("Can't write file"); return; } strcpy(temp_dir, str); - waitcursor(1); + //XXX waitcursor(1); /* The header part of the STL */ /* First 80 characters are a title or whatever you want. @@ -2552,14 +2357,14 @@ void write_stl(char *str) fprintf(fpSTL, "Binary STL output from Blender: %-48.48s ", str); /* Write all selected mesh objects */ - base= G.scene->base.first; + base= scene->base.first; while(base) { if (base->flag & SELECT) { ob = base->object; if (ob->type == OB_MESH) { me = ob->data; if (me) - numfacets += write_object_stl(fpSTL, ob, me); + numfacets += write_object_stl(fpSTL, scene, ob, me); } } base= base->next; @@ -2570,20 +2375,20 @@ void write_stl(char *str) */ fseek(fpSTL, 80, SEEK_SET); - if (G.order==B_ENDIAN) { + if (ENDIAN_ORDER==B_ENDIAN) { SWITCH_INT(numfacets); } fwrite(&numfacets, 4*sizeof(char), 1, fpSTL); fclose(fpSTL); - waitcursor(0); + //XXX waitcursor(0); } -static void write_videoscape_mesh(Object *ob, char *str) +static void write_videoscape_mesh(Scene *scene, Object *ob, char *str) { - EditMesh *em = G.editMesh; - Mesh *me; + Mesh *me= ob->data; + EditMesh *em = BKE_mesh_get_editmesh(me); Material *ma; MFace *mface; FILE *fp; @@ -2592,7 +2397,7 @@ static void write_videoscape_mesh(Object *ob, char *str) unsigned int kleur[32]; float co[3]; int a; - long tot; + intptr_t tot; char *cp; if(ob && ob->type==OB_MESH); @@ -2611,7 +2416,7 @@ static void write_videoscape_mesh(Object *ob, char *str) cp[1]= (unsigned char) (255.0*ma->b); cp[2]= (unsigned char) (255.0*ma->g); cp[3]= (unsigned char) (255.0*ma->r); - if(G.order==L_ENDIAN) SWITCH_INT(kleur[a]); + if(ENDIAN_ORDER==L_ENDIAN) SWITCH_INT(kleur[a]); } else kleur[a]= 0x00C0C0C0; @@ -2623,9 +2428,9 @@ static void write_videoscape_mesh(Object *ob, char *str) fprintf(fp,"3DG1\n"); - if(G.obedit) { + if(em) { - fprintf(fp, "%d\n", G.totvert); + fprintf(fp, "%d\n", em->totvert); tot= 0; eve= em->verts.first; @@ -2642,24 +2447,24 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, + (intptr_t) evl->v1->tmp.l, + (intptr_t) evl->v2->tmp.l, + (intptr_t) evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, - (long int) evl->v4->tmp.l, + (intptr_t) evl->v1->tmp.l, + (intptr_t) evl->v2->tmp.l, + (intptr_t) evl->v3->tmp.l, + (intptr_t) evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; } } else { - DerivedMesh *dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); me= ob->data; @@ -2673,10 +2478,10 @@ static void write_videoscape_mesh(Object *ob, char *str) } for(a=0; a<me->totface; a++, mface++) { if(mface->v4==0) { - fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[mface->mat_nr]); + fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[(int)mface->mat_nr]); } else { - fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[mface->mat_nr]); + fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[(int)mface->mat_nr]); } } @@ -2684,11 +2489,13 @@ static void write_videoscape_mesh(Object *ob, char *str) } fclose(fp); + + if (em) BKE_mesh_end_editmesh(me, em); } -void write_videoscape(char *str) +void write_videoscape(Scene *scene, char *str) { Base *base; int file, val, lampdone=0; @@ -2702,15 +2509,16 @@ void write_videoscape(char *str) file= open(str,O_BINARY|O_RDONLY); close(file); - if(file>-1) if(!during_script() && saveover(str)==0) return; + //XXX saveover() + // if(file>-1) if(!during_script() && saveover(str)==0) return; strcpy(temp_dir, str); - base= G.scene->base.first; + base= scene->base.first; while(base) { - if((base->flag & SELECT) && (base->lay & G.scene->lay)) { + if((base->flag & SELECT) && (base->lay & scene->lay)) { if(base->object->type==OB_MESH) { - write_videoscape_mesh(base->object, str); + write_videoscape_mesh(scene, base->object, str); val = BLI_stringdec(str, head, tail, &numlen); BLI_stringenc(str, head, tail, numlen, val + 1); } @@ -3007,7 +2815,7 @@ static void write_object_vrml(FILE *fp, Object *ob) } -void write_vrml(char *str) +void write_vrml(Scene *scene, char *str) { Mesh *me; Material *ma; @@ -3017,22 +2825,21 @@ void write_vrml(char *str) if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0; if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0; if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl"); - - if(!during_script() && saveover(str)==0) return; + //XXX saveover() if(!during_script() && saveover(str)==0) return; fp= fopen(str, "w"); if(fp==NULL && !during_script()) { - error("Can't write file"); + //XXX error("Can't write file"); return; } strcpy(temp_dir, str); - waitcursor(1); + //XXX waitcursor(1); /* FIRST: write all the datablocks */ - fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V%d\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n", G.version); + fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V%d\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n", BLENDER_VERSION); fprintf(fp, "Separator {\n"); fprintf(fp, "Switch {\n"); @@ -3047,7 +2854,7 @@ void write_vrml(char *str) /* only write meshes we're using in this scene */ flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0); - for(base= G.scene->base.first; base; base= base->next) + for(base= scene->base.first; base; base= base->next) if(base->object->type== OB_MESH) ((ID *)base->object->data)->flag |= LIB_DOIT; @@ -3061,10 +2868,10 @@ void write_vrml(char *str) /* THEN:Hidden Objects */ fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n"); - base= G.scene->base.first; + base= scene->base.first; while(base) { if(base->object->type== OB_MESH) { - if( (base->lay & G.scene->lay)==0 ) { + if( (base->lay & scene->lay)==0 ) { write_object_vrml(fp, base->object); } } @@ -3077,14 +2884,14 @@ void write_vrml(char *str) /* The camera */ - write_camera_vrml(fp, G.scene->camera); + write_camera_vrml(fp, scene->camera); /* THEN:The Objects */ - base= G.scene->base.first; + base= scene->base.first; while(base) { if(base->object->type== OB_MESH) { - if(base->lay & G.scene->lay) { + if(base->lay & scene->lay) { write_object_vrml(fp, base->object); } } @@ -3096,7 +2903,7 @@ void write_vrml(char *str) fclose(fp); - waitcursor(0); + //XXX waitcursor(0); } @@ -3260,7 +3067,7 @@ static void write_mesh_dxf(FILE *fp, Mesh *me) /* Write a face color */ if (me->totcol) { - ma= me->mat[mface->mat_nr]; + ma= me->mat[(int)mface->mat_nr]; if(ma) { sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b)); write_group(62, str); /* Color index */ @@ -3319,7 +3126,7 @@ static void write_object_dxf(FILE *fp, Object *ob, int layer) fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */ } -void write_dxf(char *str) +void write_dxf(struct Scene *scene, char *str) { Mesh *me; Base *base; @@ -3331,19 +3138,19 @@ void write_dxf(char *str) if (!during_script()) { if (BLI_exists(str)) - if(saveover(str)==0) - return; + ; //XXX if(saveover(str)==0) + // return; } fp= fopen(str, "w"); if(fp==NULL && !during_script()) { - error("Can't write file"); + //XXX error("Can't write file"); return; } strcpy(temp_dir, str); - waitcursor(1); + //XXX waitcursor(1); /* The header part of the DXF */ @@ -3360,7 +3167,7 @@ void write_dxf(char *str) /* only write meshes we're using in this scene */ flag_listbase_ids(&G.main->mesh, LIB_DOIT, 0); - for(base= G.scene->base.first; base; base= base->next) + for(base= scene->base.first; base; base= base->next) if(base->object->type== OB_MESH) ((ID *)base->object->data)->flag |= LIB_DOIT; @@ -3381,7 +3188,7 @@ void write_dxf(char *str) write_group(2, "ENTITIES"); /* Write all the mesh objects */ - base= G.scene->base.first; + base= scene->base.first; while(base) { if(base->object->type== OB_MESH) { write_object_dxf(fp, base->object, base->lay); @@ -3396,7 +3203,7 @@ void write_dxf(char *str) write_group(0, "EOF"); fclose(fp); - waitcursor(0); + //XXX waitcursor(0); } @@ -3451,12 +3258,12 @@ static int dxf_get_layer_col(char *layer) return 1; } -static int dxf_get_layer_num(char *layer) +static int dxf_get_layer_num(Scene *scene, char *layer) { int ret = 0; if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer); - if (ret == 0) ret = G.scene->lay; + if (ret == 0) ret = scene->lay; return ret; } @@ -3523,13 +3330,14 @@ static int read_groupf(char *str) return ret; } -#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);error(errmsg); return;} +//XXX error() is now printf until we have a callback error +#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);printf("%s", errmsg); return;} #define read_group(id,str) {id= read_groupf(str); id_test(id);} #define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0) #define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0) -#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); error("Error parsing dxf, near line %d", dxf_line); return;} +#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); printf("Error parsing dxf, near line %d", dxf_line); return;} static int id; static char val[256]; @@ -3627,22 +3435,22 @@ static float zerovec[3]= {0.0, 0.0, 0.0}; #define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0 -static void dxf_get_mesh(Mesh** m, Object** o, int noob) +static void dxf_get_mesh(Scene *scene, Mesh** m, Object** o, int noob) { Mesh *me = NULL; Object *ob; if (!noob) { - *o = add_object(OB_MESH); + *o = add_object(scene, OB_MESH); ob = *o; if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname); else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname); - if (strlen(layname)) ob->lay= dxf_get_layer_num(layname); - else ob->lay= G.scene->lay; + if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname); + else ob->lay= scene->lay; // not nice i know... but add_object() sets active base, which needs layer setting too (ton) - G.scene->basact->lay= ob->lay; + scene->basact->lay= ob->lay; *m = ob->data; me= *m; @@ -3651,7 +3459,7 @@ static void dxf_get_mesh(Mesh** m, Object** o, int noob) } else { *o = NULL; - *m = add_mesh("Mesh"); G.totmesh++; + *m = add_mesh("Mesh"); me = *m; ob = *o; @@ -3669,7 +3477,7 @@ static void dxf_get_mesh(Mesh** m, Object** o, int noob) me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0); } -static void dxf_read_point(int noob) { +static void dxf_read_point(Scene *scene, int noob) { /* Blender vars */ Object *ob; Mesh *me; @@ -3698,7 +3506,7 @@ static void dxf_read_point(int noob) { read_group(id, val); } - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); me->totvert= 1; me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); CustomData_set_layer(&me->vdata, CD_MVERT, me->mvert); @@ -3728,7 +3536,7 @@ static void dxf_close_line(void) linehold=NULL; } -static void dxf_read_line(int noob) { +static void dxf_read_line(Scene *scene, int noob) { /* Entity specific vars */ float epoint[3]={0.0, 0.0, 0.0}; short vspace=0; /* Whether or not coords are relative */ @@ -3778,7 +3586,7 @@ static void dxf_read_line(int noob) { dxf_close_line(); if (linemhold==NULL) { - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); if(ob) VECCOPY(ob->loc, cent); @@ -3840,7 +3648,7 @@ static void dxf_close_2dpoly(void) p2dhold=NULL; } -static void dxf_read_ellipse(int noob) +static void dxf_read_ellipse(Scene *scene, int noob) { /* @@ -3986,7 +3794,7 @@ static void dxf_read_ellipse(int noob) cent[2]= center[2]; #endif - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); strcpy(oldllay, layname); if(ob) VECCOPY(ob->loc, cent); dxf_add_mat (ob, me, color, layname); @@ -4036,7 +3844,7 @@ static void dxf_read_ellipse(int noob) } } -static void dxf_read_arc(int noob) +static void dxf_read_arc(Scene *scene, int noob) { /* Entity specific vars */ float epoint[3]={0.0, 0.0, 0.0}; @@ -4114,7 +3922,7 @@ static void dxf_read_arc(int noob) cent[1]= center[1]+dia*cos(phi); cent[2]= center[2]; - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); strcpy(oldllay, layname); if(ob) VECCOPY(ob->loc, cent); dxf_add_mat (ob, me, color, layname); @@ -4159,7 +3967,7 @@ static void dxf_read_arc(int noob) } } -static void dxf_read_polyline(int noob) { +static void dxf_read_polyline(Scene *scene, int noob) { /* Entity specific vars */ short vspace=0; /* Whether or not coords are relative */ int flag=0; @@ -4208,7 +4016,7 @@ static void dxf_read_polyline(int noob) { dxf_close_2dpoly(); if (p2dmhold==NULL) { - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); strcpy(oldplay, layname); @@ -4284,7 +4092,7 @@ static void dxf_read_polyline(int noob) { lwasp2d=1; } else if (flag&64) { - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); if(ob) VECCOPY(ob->loc, cent); @@ -4342,7 +4150,7 @@ static void dxf_read_polyline(int noob) { } else if (vflags & 128) { if(vids[2]==0) { - error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line); + //XXX error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line); error_exit=1; fclose(dxf_fp); @@ -4374,7 +4182,7 @@ static void dxf_read_polyline(int noob) { mface->mat_nr= 0; } else { - error("Error parsing dxf, unknown polyline information near %d", dxf_line); + //XXX error("Error parsing dxf, unknown polyline information near %d", dxf_line); error_exit=1; fclose(dxf_fp); @@ -4385,7 +4193,7 @@ static void dxf_read_polyline(int noob) { } } -static void dxf_read_lwpolyline(int noob) { +static void dxf_read_lwpolyline(Scene *scene, int noob) { /* Entity specific vars */ short vspace=0; /* Whether or not coords are relative */ int flag=0; @@ -4435,7 +4243,7 @@ static void dxf_read_lwpolyline(int noob) { if (nverts == 0) return; - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); strcpy(oldllay, layname); if(ob) VECCOPY(ob->loc, cent); dxf_add_mat (ob, me, color, layname); @@ -4454,14 +4262,14 @@ static void dxf_read_lwpolyline(int noob) { if (id == 10) { vert[0]= (float) atof(val); } else { - error("Error parsing dxf, expected (10, <x>) at line %d", dxf_line); + //XXX error("Error parsing dxf, expected (10, <x>) at line %d", dxf_line); } read_group(id,val); if (id == 20) { vert[1]= (float) atof(val); } else { - error("Error parsing dxf, expected (20, <y>) at line %d", dxf_line); + //XXX error("Error parsing dxf, expected (20, <y>) at line %d", dxf_line); } mvert = &me->mvert[v]; @@ -4509,7 +4317,7 @@ static void dxf_close_3dface(void) f3dhold=NULL; } -static void dxf_read_3dface(int noob) +static void dxf_read_3dface(Scene *scene, int noob) { /* Entity specific vars */ float vert2[3]={0.0, 0.0, 0.0}; @@ -4597,7 +4405,7 @@ static void dxf_read_3dface(int noob) dxf_close_3dface(); if(nverts<3) { - error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line); + //XXX error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line); error_exit=1; fclose(dxf_fp); @@ -4605,7 +4413,7 @@ static void dxf_read_3dface(int noob) } if (f3dmhold==NULL) { - dxf_get_mesh(&me, &ob, noob); + dxf_get_mesh(scene, &me, &ob, noob); strcpy(oldflay, layname); @@ -4672,7 +4480,7 @@ static void dxf_read_3dface(int noob) hasbumped=1; } -static void dxf_read(char *filename) +static void dxf_read(Scene *scene, char *filename) { Mesh *lastMe = G.main->mesh.last; @@ -4710,7 +4518,7 @@ static void dxf_read(char *filename) } else if (id==3) { /* Now the object def should follow */ if(strlen(entname)==0) { - error("Error parsing dxf, no mesh name near %d", dxf_line); + //XXX error("Error parsing dxf, no mesh name near %d", dxf_line); fclose(dxf_fp); return; } @@ -4720,7 +4528,7 @@ static void dxf_read(char *filename) read_group(id, val); if(group_is(0, "POLYLINE")) { - dxf_read_polyline(1); + dxf_read_polyline(scene, 1); if(error_exit) return; lwasf3d=0; lwasline=0; @@ -4728,7 +4536,7 @@ static void dxf_read(char *filename) while(group_isnt(0, "SEQEND")) read_group(id, val); } else if(group_is(0, "LWPOLYLINE")) { - dxf_read_lwpolyline(1); + dxf_read_lwpolyline(scene, 1); if(error_exit) return; lwasf3d=0; lwasline=0; @@ -4740,27 +4548,27 @@ static void dxf_read(char *filename) lwasp2d=0; lwasline=0; } else if(group_is(0, "POINT")) { - dxf_read_point(1); + dxf_read_point(scene, 1); if(error_exit) return; lwasf3d=0; lwasp2d=0; lwasline=0; } else if(group_is(0, "LINE")) { - dxf_read_line(1); + dxf_read_line(scene, 1); if(error_exit) return; lwasline=1; lwasp2d=0; lwasf3d=0; } else if(group_is(0, "3DFACE")) { - dxf_read_3dface(1); + dxf_read_3dface(scene, 1); if(error_exit) return; lwasf3d=1; lwasp2d=0; lwasline=0; } else if (group_is(0, "CIRCLE")) { - dxf_read_arc(1); + dxf_read_arc(scene, 1); } else if (group_is(0, "ELLIPSE")) { - dxf_read_ellipse(1); + dxf_read_ellipse(scene, 1); } else if (group_is(0, "ENDBLK")) { break; } @@ -4820,7 +4628,7 @@ static void dxf_read(char *filename) } if(strlen(obname)==0) { - error("Error parsing dxf, no object name near %d", dxf_line); + //XXX error("Error parsing dxf, no object name near %d", dxf_line); fclose(dxf_fp); return; } @@ -4844,8 +4652,6 @@ static void dxf_read(char *filename) ob->dupsta= 1; ob->dupend= 100; ob->recalc= OB_RECALC; /* needed because of weird way of adding libdata directly */ - G.totobj++; - ob->data= obdata; ((ID*)ob->data)->us++; @@ -4862,12 +4668,12 @@ static void dxf_read(char *filename) I leave it commented out here as warning (ton) */ //for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i]; - if (strlen(layname)) ob->lay= dxf_get_layer_num(layname); - else ob->lay= G.scene->lay; + if (strlen(layname)) ob->lay= dxf_get_layer_num(scene, layname); + else ob->lay= scene->lay; /* link to scene */ base= MEM_callocN( sizeof(Base), "add_base"); - BLI_addhead(&G.scene->base, base); + BLI_addhead(&scene->base, base); base->lay= ob->lay; @@ -4880,7 +4686,7 @@ static void dxf_read(char *filename) lwasp2d=0; lwasline=0; } else if(group_is(0, "POLYLINE")) { - dxf_read_polyline(0); + dxf_read_polyline(scene, 0); if(error_exit) return; lwasf3d=0; lwasline=0; @@ -4888,7 +4694,7 @@ static void dxf_read(char *filename) while(group_isnt(0, "SEQEND")) read_group(id, val); } else if(group_is(0, "LWPOLYLINE")) { - dxf_read_lwpolyline(0); + dxf_read_lwpolyline(scene, 0); if(error_exit) return; lwasf3d=0; lwasline=0; @@ -4900,27 +4706,27 @@ static void dxf_read(char *filename) lwasp2d=0; lwasline=0; } else if(group_is(0, "POINT")) { - dxf_read_point(0); + dxf_read_point(scene, 0); if(error_exit) return; lwasf3d=0; lwasp2d=0; lwasline=0; } else if(group_is(0, "LINE")) { - dxf_read_line(0); + dxf_read_line(scene, 0); if(error_exit) return; lwasline=1; lwasp2d=0; lwasf3d=0; } else if(group_is(0, "3DFACE")) { - dxf_read_3dface(0); + dxf_read_3dface(scene, 0); if(error_exit) return; lwasline=0; lwasp2d=0; lwasf3d=1; } else if (group_is(0, "CIRCLE") || group_is(0, "ARC")) { - dxf_read_arc(0); + dxf_read_arc(scene, 0); } else if (group_is(0, "ELLIPSE")) { - dxf_read_ellipse(0); + dxf_read_ellipse(scene, 0); } else if(group_is(0, "ENDSEC")) { break; } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c new file mode 100644 index 00000000000..ad8115ba9aa --- /dev/null +++ b/source/blender/blenkernel/intern/fcurve.c @@ -0,0 +1,2339 @@ +/* Testing code for new animation system in 2.5 + * Copyright 2009, Joshua Leung + */ + + +#include <math.h> +#include <stdio.h> +#include <stddef.h> +#include <string.h> +#include <float.h> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_noise.h" + +#include "BKE_fcurve.h" +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_idprop.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#ifndef DISABLE_PYTHON +#include "BPY_extern.h" /* for BPY_pydriver_eval() */ +#endif + +#define SMALL -1.0e-10 +#define SELECT 1 + +/* ************************** Data-Level Functions ************************* */ + +/* ---------------------- Freeing --------------------------- */ + +/* Frees the F-Curve itself too, so make sure BLI_remlink is called before calling this... */ +void free_fcurve (FCurve *fcu) +{ + if (fcu == NULL) + return; + + /* free curve data */ + if (fcu) { + if (fcu->bezt) MEM_freeN(fcu->bezt); + if (fcu->fpt) MEM_freeN(fcu->fpt); + } + + /* free RNA-path, as this were allocated when getting the path string */ + if (fcu->rna_path) + MEM_freeN(fcu->rna_path); + + /* free extra data - i.e. modifiers, and driver */ + fcurve_free_driver(fcu); + fcurve_free_modifiers(fcu); + + /* free f-curve itself */ + MEM_freeN(fcu); +} + +/* Frees a list of F-Curves */ +void free_fcurves (ListBase *list) +{ + FCurve *fcu, *fcn; + + /* sanity check */ + if (list == NULL) + return; + + /* free data - no need to call remlink before freeing each curve, + * as we store reference to next, and freeing only touches the curve + * it's given + */ + for (fcu= list->first; fcu; fcu= fcn) { + fcn= fcu->next; + free_fcurve(fcu); + } + + /* clear pointers just in case */ + list->first= list->last= NULL; +} + +/* ---------------------- Copy --------------------------- */ + +/* duplicate an F-Curve */ +FCurve *copy_fcurve (FCurve *fcu) +{ + FCurve *fcu_d; + + /* sanity check */ + if (fcu == NULL) + return NULL; + + /* make a copy */ + fcu_d= MEM_dupallocN(fcu); + + fcu_d->next= fcu_d->prev= NULL; + fcu_d->grp= NULL; + + /* copy curve data */ + fcu_d->bezt= MEM_dupallocN(fcu_d->bezt); + fcu_d->fpt= MEM_dupallocN(fcu_d->fpt); + + /* copy rna-path */ + fcu_d->rna_path= MEM_dupallocN(fcu_d->rna_path); + + /* copy driver */ + fcu_d->driver= fcurve_copy_driver(fcu_d->driver); + + /* copy modifiers */ + fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers); + + /* return new data */ + return fcu_d; +} + +/* duplicate a list of F-Curves */ +void copy_fcurves (ListBase *dst, ListBase *src) +{ + FCurve *dfcu, *sfcu; + + /* sanity checks */ + if ELEM(NULL, dst, src) + return; + + /* clear destination list first */ + dst->first= dst->last= NULL; + + /* copy one-by-one */ + for (sfcu= src->first; sfcu; sfcu= sfcu->next) { + dfcu= copy_fcurve(sfcu); + BLI_addtail(dst, dfcu); + } +} + +/* ---------------------- Relink --------------------------- */ + +#if 0 +/* uses id->newid to match pointers with other copied data + * - called after single-user or other such + */ + if (icu->driver) + ID_NEW(icu->driver->ob); +#endif + +/* --------------------- Finding -------------------------- */ + +/* Find the F-Curve affecting the given RNA-access path + index, in the list of F-Curves provided */ +FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array_index) +{ + FCurve *fcu; + + /* sanity checks */ + if ( ELEM(NULL, list, rna_path) || (array_index < 0) ) + return NULL; + + /* check paths of curves, then array indices... */ + for (fcu= list->first; fcu; fcu= fcu->next) { + /* simple string-compare (this assumes that they have the same root...) */ + if (fcu->rna_path && !strcmp(fcu->rna_path, rna_path)) { + /* now check indicies */ + if (fcu->array_index == array_index) + return fcu; + } + } + + /* return */ + return NULL; +} + +short on_keyframe_fcurve(FCurve *fcu, float cfra) +{ + BezTriple *bezt; + unsigned i; + + bezt= fcu->bezt; + for (i=0; i<fcu->totvert; i++, bezt++) { + if (IS_EQ(bezt->vec[1][0], cfra)) + return 1; + } + + return 0; +} + +/* Calculate the extents of F-Curve's data */ +void calc_fcurve_bounds (FCurve *fcu, float *xmin, float *xmax, float *ymin, float *ymax) +{ + float xminv=999999999.0f, xmaxv=-999999999.0f; + float yminv=999999999.0f, ymaxv=-999999999.0f; + short foundvert=0; + unsigned int i; + + if (fcu->totvert) { + if (fcu->bezt) { + /* frame range can be directly calculated from end verts */ + if (xmin || xmax) { + xminv= MIN2(xminv, fcu->bezt[0].vec[1][0]); + xmaxv= MAX2(xmaxv, fcu->bezt[fcu->totvert-1].vec[1][0]); + } + + /* only loop over keyframes to find extents for values if needed */ + if (ymin || ymax) { + BezTriple *bezt; + + for (bezt=fcu->bezt, i=0; i < fcu->totvert; bezt++, i++) { + if (bezt->vec[1][1] < yminv) + yminv= bezt->vec[1][1]; + if (bezt->vec[1][1] > ymaxv) + ymaxv= bezt->vec[1][1]; + } + } + } + else if (fcu->fpt) { + /* frame range can be directly calculated from end verts */ + if (xmin || xmax) { + xminv= MIN2(xminv, fcu->fpt[0].vec[0]); + xmaxv= MAX2(xmaxv, fcu->fpt[fcu->totvert-1].vec[0]); + } + + /* only loop over keyframes to find extents for values if needed */ + if (ymin || ymax) { + FPoint *fpt; + + for (fpt=fcu->fpt, i=0; i < fcu->totvert; fpt++, i++) { + if (fpt->vec[1] < yminv) + yminv= fpt->vec[1]; + if (fpt->vec[1] > ymaxv) + ymaxv= fpt->vec[1]; + } + } + } + + foundvert=1; + } + + /* minimum sizes are 1.0f */ + if (foundvert) { + if (xminv == xmaxv) xmaxv += 1.0f; + if (yminv == ymaxv) ymaxv += 1.0f; + + if (xmin) *xmin= xminv; + if (xmax) *xmax= xmaxv; + + if (ymin) *ymin= yminv; + if (ymax) *ymax= ymaxv; + } + else { + if (xmin) *xmin= 0.0f; + if (xmax) *xmax= 0.0f; + + if (ymin) *ymin= 1.0f; + if (ymax) *ymax= 1.0f; + } +} + +/* Calculate the extents of F-Curve's keyframes */ +void calc_fcurve_range (FCurve *fcu, float *start, float *end) +{ + float min=999999999.0f, max=-999999999.0f; + short foundvert=0; + + if (fcu->totvert) { + if (fcu->bezt) { + min= MIN2(min, fcu->bezt[0].vec[1][0]); + max= MAX2(max, fcu->bezt[fcu->totvert-1].vec[1][0]); + } + else if (fcu->fpt) { + min= MIN2(min, fcu->fpt[0].vec[0]); + max= MAX2(max, fcu->fpt[fcu->totvert-1].vec[0]); + } + + foundvert=1; + } + + /* minimum length is 1 frame */ + if (foundvert) { + if (min == max) max += 1.0f; + *start= min; + *end= max; + } + else { + *start= 0.0f; + *end= 1.0f; + } +} + +/* ***************************** Keyframe Column Tools ********************************* */ + +/* add a BezTriple to a column */ +void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt) +{ + CfraElem *ce, *cen; + + for (ce= lb->first; ce; ce= ce->next) { + /* double key? */ + if (ce->cfra == bezt->vec[1][0]) { + if (bezt->f2 & SELECT) ce->sel= bezt->f2; + return; + } + /* should key be inserted before this column? */ + else if (ce->cfra > bezt->vec[1][0]) break; + } + + /* create a new column */ + cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); + if (ce) BLI_insertlinkbefore(lb, ce, cen); + else BLI_addtail(lb, cen); + + cen->cfra= bezt->vec[1][0]; + cen->sel= bezt->f2; +} + +/* ***************************** Samples Utilities ******************************* */ +/* Some utilities for working with FPoints (i.e. 'sampled' animation curve data, such as + * data imported from BVH/Mocap files), which are specialised for use with high density datasets, + * which BezTriples/Keyframe data are ill equipped to do. + */ + + +/* Basic sampling callback which acts as a wrapper for evaluate_fcurve() + * 'data' arg here is unneeded here... + */ +float fcurve_samplingcb_evalcurve (FCurve *fcu, void *data, float evaltime) +{ + /* assume any interference from drivers on the curve is intended... */ + return evaluate_fcurve(fcu, evaltime); +} + + +/* Main API function for creating a set of sampled curve data, given some callback function + * used to retrieve the values to store. + */ +void fcurve_store_samples (FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb) +{ + FPoint *fpt, *new_fpt; + int cfra; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, sample_cb) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + if (start >= end) { + printf("Error: Frame range for Sampled F-Curve creation is inappropriate \n"); + return; + } + + /* set up sample data */ + fpt= new_fpt= MEM_callocN(sizeof(FPoint)*(end-start+1), "FPoint Samples"); + + /* use the sampling callback at 1-frame intervals from start to end frames */ + for (cfra= start; cfra <= end; cfra++, fpt++) { + fpt->vec[0]= (float)cfra; + fpt->vec[1]= sample_cb(fcu, data, (float)cfra); + } + + /* free any existing sample/keyframe data on curve */ + if (fcu->bezt) MEM_freeN(fcu->bezt); + if (fcu->fpt) MEM_freeN(fcu->fpt); + + /* store the samples */ + fcu->bezt= NULL; + fcu->fpt= new_fpt; + fcu->totvert= end - start + 1; +} + +/* ***************************** F-Curve Sanity ********************************* */ +/* The functions here are used in various parts of Blender, usually after some editing + * of keyframe data has occurred. They ensure that keyframe data is properly ordered and + * that the handles are correctly + */ + +/* This function recalculates the handles of an F-Curve + * If the BezTriples have been rearranged, sort them first before using this. + */ +void calchandles_fcurve (FCurve *fcu) +{ + BezTriple *bezt, *prev, *next; + int a= fcu->totvert; + + /* Error checking: + * - need at least two points + * - need bezier keys + * - only bezier-interpolation has handles (for now) + */ + if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/) + return; + + /* get initial pointers */ + bezt= fcu->bezt; + prev= NULL; + next= (bezt + 1); + + /* loop over all beztriples, adjusting handles */ + while (a--) { + /* clamp timing of handles to be on either side of beztriple */ + if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0]; + if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0]; + + /* calculate auto-handles */ + if (fcu->flag & FCURVE_AUTO_HANDLES) + calchandleNurb(bezt, prev, next, 2); /* 2==special autohandle && keep extrema horizontal */ + else + calchandleNurb(bezt, prev, next, 1); /* 1==special autohandle */ + + /* for automatic ease in and out */ + if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) { + /* only do this on first or last beztriple */ + if ((a == 0) || (a == fcu->totvert-1)) { + /* set both handles to have same horizontal value as keyframe */ + if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) { + bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; + } + } + } + + /* advance pointers for next iteration */ + prev= bezt; + if (a == 1) next= NULL; + else next++; + bezt++; + } +} + +/* Use when F-Curve with handles has changed + * It treats all BezTriples with the following rules: + * - PHASE 1: do types have to be altered? + * -> Auto handles: become aligned when selection status is NOT(000 || 111) + * -> Vector handles: become 'nothing' when (one half selected AND other not) + * - PHASE 2: recalculate handles +*/ +void testhandles_fcurve (FCurve *fcu) +{ + BezTriple *bezt; + unsigned int a; + + /* only beztriples have handles (bpoints don't though) */ + if ELEM(NULL, fcu, fcu->bezt) + return; + + /* loop over beztriples */ + for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) { + short flag= 0; + + /* flag is initialised as selection status + * of beztriple control-points (labelled 0,1,2) + */ + if (bezt->f1 & SELECT) flag |= (1<<0); // == 1 + if (bezt->f2 & SELECT) flag |= (1<<1); // == 2 + if (bezt->f3 & SELECT) flag |= (1<<2); // == 4 + + /* one or two handles selected only */ + if (ELEM(flag, 0, 7)==0) { + /* auto handles become aligned */ + if (bezt->h1==HD_AUTO) + bezt->h1= HD_ALIGN; + if (bezt->h2==HD_AUTO) + bezt->h2= HD_ALIGN; + + /* vector handles become 'free' when only one half selected */ + if (bezt->h1==HD_VECT) { + /* only left half (1 or 2 or 1+2) */ + if (flag < 4) + bezt->h1= 0; + } + if (bezt->h2==HD_VECT) { + /* only right half (4 or 2+4) */ + if (flag > 3) + bezt->h2= 0; + } + } + } + + /* recalculate handles */ + calchandles_fcurve(fcu); +} + +/* This function sorts BezTriples so that they are arranged in chronological order, + * as tools working on F-Curves expect that the BezTriples are in order. + */ +void sort_time_fcurve (FCurve *fcu) +{ + short ok= 1; + + /* keep adjusting order of beztriples until nothing moves (bubble-sort) */ + while (ok) { + ok= 0; + + /* currently, will only be needed when there are beztriples */ + if (fcu->bezt) { + BezTriple *bezt; + unsigned int a; + + /* loop over ALL points to adjust position in array and recalculate handles */ + for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) { + /* check if thee's a next beztriple which we could try to swap with current */ + if (a < (fcu->totvert-1)) { + /* swap if one is after the other (and indicate that order has changed) */ + if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) { + SWAP(BezTriple, *bezt, *(bezt+1)); + ok= 1; + } + + /* if either one of both of the points exceeds crosses over the keyframe time... */ + if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) { + /* swap handles if they have switched sides for some reason */ + SWAP(float, bezt->vec[0][0], bezt->vec[2][0]); + SWAP(float, bezt->vec[0][1], bezt->vec[2][1]); + } + else { + /* clamp handles */ + if (bezt->vec[0][0] > bezt->vec[1][0]) + bezt->vec[0][0]= bezt->vec[1][0]; + if (bezt->vec[2][0] < bezt->vec[1][0]) + bezt->vec[2][0]= bezt->vec[1][0]; + } + } + } + } + } +} + +/* This function tests if any BezTriples are out of order, thus requiring a sort */ +short test_time_fcurve (FCurve *fcu) +{ + unsigned int a; + + /* sanity checks */ + if (fcu == NULL) + return 0; + + /* currently, only need to test beztriples */ + if (fcu->bezt) { + BezTriple *bezt; + + /* loop through all BezTriples, stopping when one exceeds the one after it */ + for (a=0, bezt= fcu->bezt; a < (fcu->totvert - 1); a++, bezt++) { + if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) + return 1; + } + } + else if (fcu->fpt) { + FPoint *fpt; + + /* loop through all FPoints, stopping when one exceeds the one after it */ + for (a=0, fpt= fcu->fpt; a < (fcu->totvert - 1); a++, fpt++) { + if (fpt->vec[0] > (fpt+1)->vec[0]) + return 1; + } + } + + /* none need any swapping */ + return 0; +} + +/* ***************************** Drivers ********************************* */ + +/* Driver API --------------------------------- */ + +/* This frees the driver target itself */ +void driver_free_target (ChannelDriver *driver, DriverTarget *dtar) +{ + /* sanity checks */ + if (dtar == NULL) + return; + + /* free target vars */ + if (dtar->rna_path) + MEM_freeN(dtar->rna_path); + + /* remove the target from the driver */ + if (driver) + BLI_freelinkN(&driver->targets, dtar); + else + MEM_freeN(dtar); +} + +/* Add a new driver target variable */ +DriverTarget *driver_add_new_target (ChannelDriver *driver) +{ + DriverTarget *dtar; + + /* sanity checks */ + if (driver == NULL) + return NULL; + + /* make a new target */ + dtar= MEM_callocN(sizeof(DriverTarget), "DriverTarget"); + BLI_addtail(&driver->targets, dtar); + + /* give the target a 'unique' name */ + strcpy(dtar->name, "var"); + BLI_uniquename(&driver->targets, dtar, "var", '_', offsetof(DriverTarget, name), 64); + + /* return the target */ + return dtar; +} + +/* This frees the driver itself */ +void fcurve_free_driver(FCurve *fcu) +{ + ChannelDriver *driver; + DriverTarget *dtar, *dtarn; + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->driver) + return; + driver= fcu->driver; + + /* free driver targets */ + for (dtar= driver->targets.first; dtar; dtar= dtarn) { + dtarn= dtar->next; + driver_free_target(driver, dtar); + } + + /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */ + MEM_freeN(driver); + fcu->driver= NULL; +} + +/* This makes a copy of the given driver */ +ChannelDriver *fcurve_copy_driver (ChannelDriver *driver) +{ + ChannelDriver *ndriver; + DriverTarget *dtar; + + /* sanity checks */ + if (driver == NULL) + return NULL; + + /* copy all data */ + ndriver= MEM_dupallocN(driver); + + /* copy targets */ + ndriver->targets.first= ndriver->targets.last= NULL; + BLI_duplicatelist(&ndriver->targets, &driver->targets); + + for (dtar= ndriver->targets.first; dtar; dtar= dtar->next) { + /* make a copy of target's rna path if available */ + if (dtar->rna_path) + dtar->rna_path = MEM_dupallocN(dtar->rna_path); + } + + /* return the new driver */ + return ndriver; +} + +/* Driver Evaluation -------------------------- */ + +/* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */ +float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + ID *id; + char *path; + int index; + float value= 0.0f; + + /* sanity check */ + if ELEM(NULL, driver, dtar) + return 0.0f; + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(dtar->id, &id_ptr); + id= dtar->id; + path= dtar->rna_path; + index= dtar->array_index; + + /* error check for missing pointer... */ + if (id == NULL) { + printf("Error: driver doesn't have any valid target to use \n"); + if (G.f & G_DEBUG) printf("\tpath = %s [%d] \n", path, index); + driver->flag |= DRIVER_FLAG_INVALID; + return 0.0f; + } + + /* get property to read from, and get value as appropriate */ + if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) { + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + if (RNA_property_array_length(prop)) + value= (float)RNA_property_boolean_get_index(&ptr, prop, index); + else + value= (float)RNA_property_boolean_get(&ptr, prop); + break; + case PROP_INT: + if (RNA_property_array_length(prop)) + value= (float)RNA_property_int_get_index(&ptr, prop, index); + else + value= (float)RNA_property_int_get(&ptr, prop); + break; + case PROP_FLOAT: + if (RNA_property_array_length(prop)) + value= RNA_property_float_get_index(&ptr, prop, index); + else + value= RNA_property_float_get(&ptr, prop); + break; + case PROP_ENUM: + value= (float)RNA_property_enum_get(&ptr, prop); + break; + default: + break; + } + } + + return value; +} + +/* Get two PoseChannels from the targets of the given Driver */ +static void driver_get_target_pchans2 (ChannelDriver *driver, bPoseChannel **pchan1, bPoseChannel **pchan2) +{ + DriverTarget *dtar; + short i = 0; + + /* before doing anything */ + *pchan1= NULL; + *pchan2= NULL; + + /* only take the first two targets */ + for (dtar= driver->targets.first; (dtar) && (i < 2); dtar=dtar->next, i++) { + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + + /* get RNA-pointer for the ID-block given in target */ + if (dtar->id) + RNA_id_pointer_create(dtar->id, &id_ptr); + else + continue; + + /* resolve path so that we have pointer to the right posechannel */ + if (RNA_path_resolve(&id_ptr, dtar->rna_path, &ptr, &prop)) { + /* is pointer valid (i.e. pointing to an actual posechannel */ + if ((ptr.type == &RNA_PoseChannel) && (ptr.data)) { + /* first or second target? */ + if (i) + *pchan1= ptr.data; + else + *pchan2= ptr.data; + } + } + } +} + +/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" + * - "evaltime" is the frame at which F-Curve is being evaluated + * - has to return a float value + */ +static float evaluate_driver (ChannelDriver *driver, float evaltime) +{ + DriverTarget *dtar; + + /* check if driver can be evaluated */ + if (driver->flag & DRIVER_FLAG_INVALID) + return 0.0f; + + // TODO: the flags for individual targets need to be used too for more fine-grained support... + switch (driver->type) { + case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ + { + /* check how many targets there are first (i.e. just one?) */ + if (driver->targets.first == driver->targets.last) { + /* just one target, so just use that */ + dtar= driver->targets.first; + return driver_get_target_value(driver, dtar); + } + else { + /* more than one target, so average the values of the targets */ + int tot = 0; + float value = 0.0f; + + /* loop through targets, adding (hopefully we don't get any overflow!) */ + for (dtar= driver->targets.first; dtar; dtar=dtar->next) { + value += driver_get_target_value(driver, dtar); + tot++; + } + + /* return the average of these */ + return (value / (float)tot); + } + } + break; + + case DRIVER_TYPE_PYTHON: /* expression */ + { +#ifndef DISABLE_PYTHON + /* check for empty or invalid expression */ + if ( (driver->expression[0] == '\0') || + (driver->flag & DRIVER_FLAG_INVALID) ) + { + return 0.0f; + } + + /* this evaluates the expression using Python,and returns its result: + * - on errors it reports, then returns 0.0f + */ + return BPY_pydriver_eval(driver); +#endif /* DISABLE_PYTHON*/ + } + break; + + + case DRIVER_TYPE_ROTDIFF: /* difference of rotations of 2 bones (should ideally be in same armature) */ + { + bPoseChannel *pchan, *pchan2; + float q1[4], q2[4], quat[4], angle; + + /* get pose channels, and check if we've got two */ + driver_get_target_pchans2(driver, &pchan, &pchan2); + if (ELEM(NULL, pchan, pchan2)) { + /* disable this driver, since it doesn't work correctly... */ + driver->flag |= DRIVER_FLAG_INVALID; + + /* check what the error was */ + if ((pchan == NULL) && (pchan2 == NULL)) + printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid \n"); + else if (pchan == NULL) + printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel \n"); + else if (pchan2 == NULL) + printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel \n"); + + /* stop here... */ + return 0.0f; + } + + /* use the final posed locations */ + Mat4ToQuat(pchan->pose_mat, q1); + Mat4ToQuat(pchan2->pose_mat, q2); + + QuatInv(q1); + QuatMul(quat, q1, q2); + angle = 2.0f * (saacos(quat[0])); + angle= ABS(angle); + + return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle); + } + break; + + default: + { + /* special 'hack' - just use stored value + * This is currently used as the mechanism which allows animated settings to be able + * to be changed via the UI. + */ + return driver->curval; + } + } + + /* return 0.0f, as couldn't find relevant data to use */ + return 0.0f; +} + +/* ***************************** Curve Calculations ********************************* */ + +/* The total length of the handles is not allowed to be more + * than the horizontal distance between (v1-v4). + * This is to prevent curve loops. +*/ +void correct_bezpart (float *v1, float *v2, float *v3, float *v4) +{ + float h1[2], h2[2], len1, len2, len, fac; + + /* calculate handle deltas */ + h1[0]= v1[0] - v2[0]; + h1[1]= v1[1] - v2[1]; + + h2[0]= v4[0] - v3[0]; + h2[1]= v4[1] - v3[1]; + + /* calculate distances: + * - len = span of time between keyframes + * - len1 = length of handle of start key + * - len2 = length of handle of end key + */ + len= v4[0]- v1[0]; + len1= (float)fabs(h1[0]); + len2= (float)fabs(h2[0]); + + /* if the handles have no length, no need to do any corrections */ + if ((len1+len2) == 0.0f) + return; + + /* the two handles cross over each other, so force them + * apart using the proportion they overlap + */ + if ((len1+len2) > len) { + fac= len / (len1+len2); + + v2[0]= (v1[0] - fac*h1[0]); + v2[1]= (v1[1] - fac*h1[1]); + + v3[0]= (v4[0] - fac*h2[0]); + v3[1]= (v4[1] - fac*h2[1]); + } +} + +/* find root ('zero') */ +int findzero (float x, float q0, float q1, float q2, float q3, float *o) +{ + double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; + int nr= 0; + + c0= q0 - x; + c1= 3.0 * (q1 - q0); + c2= 3.0 * (q0 - 2.0*q1 + q2); + c3= q3 - q0 + 3.0 * (q1 - q2); + + if (c3 != 0.0) { + a= c2/c3; + b= c1/c3; + c= c0/c3; + a= a/3; + + p= b/3 - a*a; + q= (2*a*a*a - a*b + c) / 2; + d= q*q + p*p*p; + + if (d > 0.0) { + t= sqrt(d); + o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a); + + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; + else return 0; + } + else if (d == 0.0) { + t= Sqrt3d(-q); + o[0]= (float)(2*t - a); + + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; + o[nr]= (float)(-t-a); + + if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; + else return nr; + } + else { + phi= acos(-q / sqrt(-(p*p*p))); + t= sqrt(-p); + p= cos(phi/3); + q= sqrt(3 - 3*p*p); + o[0]= (float)(2*t*p - a); + + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; + o[nr]= (float)(-t * (p + q) - a); + + if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++; + o[nr]= (float)(-t * (p - q) - a); + + if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; + else return nr; + } + } + else { + a=c2; + b=c1; + c=c0; + + if (a != 0.0) { + // discriminant + p= b*b - 4*a*c; + + if (p > 0) { + p= sqrt(p); + o[0]= (float)((-b-p) / (2 * a)); + + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; + o[nr]= (float)((-b+p)/(2*a)); + + if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; + else return nr; + } + else if (p == 0) { + o[0]= (float)(-b / (2 * a)); + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; + else return 0; + } + } + else if (b != 0.0) { + o[0]= (float)(-c/b); + + if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; + else return 0; + } + else if (c == 0.0) { + o[0]= 0.0; + return 1; + } + + return 0; + } +} + +void berekeny (float f1, float f2, float f3, float f4, float *o, int b) +{ + float t, c0, c1, c2, c3; + int a; + + c0= f1; + c1= 3.0f * (f2 - f1); + c2= 3.0f * (f1 - 2.0f*f2 + f3); + c3= f4 - f1 + 3.0f * (f2 - f3); + + for (a=0; a < b; a++) { + t= o[a]; + o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; + } +} + +void berekenx (float *f, float *o, int b) +{ + float t, c0, c1, c2, c3; + int a; + + c0= f[0]; + c1= 3.0f * (f[3] - f[0]); + c2= 3.0f * (f[0] - 2.0f*f[3] + f[6]); + c3= f[9] - f[0] + 3.0f * (f[3] - f[6]); + + for (a=0; a < b; a++) { + t= o[a]; + o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; + } +} + + +/* -------------------------- */ + +/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ +static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltime) +{ + BezTriple *bezt, *prevbezt, *lastbezt; + float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; + unsigned int a; + int b; + float cvalue = 0.0f; + + /* get pointers */ + a= fcu->totvert-1; + prevbezt= bezts; + bezt= prevbezt+1; + lastbezt= prevbezt + a; + + /* evaluation time at or past endpoints? */ + if (prevbezt->vec[1][0] >= evaltime) + { + /* before or on first keyframe */ + if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) && + !(fcu->flag & FCURVE_DISCRETE_VALUES) ) + { + /* linear or bezier interpolation */ + if (prevbezt->ipo==BEZT_IPO_LIN) + { + /* Use the next center point instead of our own handle for + * linear interpolated extrapolate + */ + if (fcu->totvert == 1) + cvalue= prevbezt->vec[1][1]; + else + { + bezt = prevbezt+1; + dx= prevbezt->vec[1][0] - evaltime; + fac= bezt->vec[1][0] - prevbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; + cvalue= prevbezt->vec[1][1] - (fac * dx); + } + else + cvalue= prevbezt->vec[1][1]; + } + } + else + { + /* Use the first handle (earlier) of first BezTriple to calculate the + * gradient and thus the value of the curve at evaltime + */ + dx= prevbezt->vec[1][0] - evaltime; + fac= prevbezt->vec[1][0] - prevbezt->vec[0][0]; + + /* prevent division by zero */ + if (fac) { + fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; + cvalue= prevbezt->vec[1][1] - (fac * dx); + } + else + cvalue= prevbezt->vec[1][1]; + } + } + else + { + /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, + * so just extend first keyframe's value + */ + cvalue= prevbezt->vec[1][1]; + } + } + else if (lastbezt->vec[1][0] <= evaltime) + { + /* after or on last keyframe */ + if ( (fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) && + !(fcu->flag & FCURVE_DISCRETE_VALUES) ) + { + /* linear or bezier interpolation */ + if (lastbezt->ipo==BEZT_IPO_LIN) + { + /* Use the next center point instead of our own handle for + * linear interpolated extrapolate + */ + if (fcu->totvert == 1) + cvalue= lastbezt->vec[1][1]; + else + { + prevbezt = lastbezt - 1; + dx= evaltime - lastbezt->vec[1][0]; + fac= lastbezt->vec[1][0] - prevbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; + cvalue= lastbezt->vec[1][1] + (fac * dx); + } + else + cvalue= lastbezt->vec[1][1]; + } + } + else + { + /* Use the gradient of the second handle (later) of last BezTriple to calculate the + * gradient and thus the value of the curve at evaltime + */ + dx= evaltime - lastbezt->vec[1][0]; + fac= lastbezt->vec[2][0] - lastbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; + cvalue= lastbezt->vec[1][1] + (fac * dx); + } + else + cvalue= lastbezt->vec[1][1]; + } + } + else + { + /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, + * so just extend last keyframe's value + */ + cvalue= lastbezt->vec[1][1]; + } + } + else + { + /* evaltime occurs somewhere in the middle of the curve */ + for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) + { + /* evaltime occurs within the interval defined by these two keyframes */ + if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) + { + /* value depends on interpolation mode */ + if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES)) + { + /* constant (evaltime not relevant, so no interpolation needed) */ + cvalue= prevbezt->vec[1][1]; + } + else if (prevbezt->ipo == BEZT_IPO_LIN) + { + /* linear - interpolate between values of the two keyframes */ + fac= bezt->vec[1][0] - prevbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac= (evaltime - prevbezt->vec[1][0]) / fac; + cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1])); + } + else + cvalue= prevbezt->vec[1][1]; + } + else + { + /* bezier interpolation */ + /* v1,v2 are the first keyframe and its 2nd handle */ + v1[0]= prevbezt->vec[1][0]; + v1[1]= prevbezt->vec[1][1]; + v2[0]= prevbezt->vec[2][0]; + v2[1]= prevbezt->vec[2][1]; + /* v3,v4 are the last keyframe's 1st handle + the last keyframe */ + v3[0]= bezt->vec[0][0]; + v3[1]= bezt->vec[0][1]; + v4[0]= bezt->vec[1][0]; + v4[1]= bezt->vec[1][1]; + + /* adjust handles so that they don't overlap (forming a loop) */ + correct_bezpart(v1, v2, v3, v4); + + /* try to get a value for this position - if failure, try another set of points */ + b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); + if (b) { + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + cvalue= opl[0]; + break; + } + } + } + } + } + + /* return value */ + return cvalue; +} + +/* Calculate F-Curve value for 'evaltime' using FPoint samples */ +static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime) +{ + FPoint *prevfpt, *lastfpt, *fpt; + float cvalue= 0.0f; + + /* get pointers */ + prevfpt= fpts; + lastfpt= prevfpt + fcu->totvert-1; + + /* evaluation time at or past endpoints? */ + if (prevfpt->vec[0] >= evaltime) { + /* before or on first sample, so just extend value */ + cvalue= prevfpt->vec[1]; + } + else if (lastfpt->vec[0] <= evaltime) { + /* after or on last sample, so just extend value */ + cvalue= lastfpt->vec[1]; + } + else { + /* find the one on the right frame (assume that these are spaced on 1-frame intervals) */ + fpt= prevfpt + (int)(evaltime - prevfpt->vec[0]); + cvalue= fpt->vec[1]; + } + + /* return value */ + return cvalue; +} + +/* ******************************** F-Curve Modifiers ********************************* */ + +/* Template --------------------------- */ + +/* Each modifier defines a set of functions, which will be called at the appropriate + * times. In addition to this, each modifier should have a type-info struct, where + * its functions are attached for use. + */ + +/* Template for type-info data: + * - make a copy of this when creating new modifiers, and just change the functions + * pointed to as necessary + * - although the naming of functions doesn't matter, it would help for code + * readability, to follow the same naming convention as is presented here + * - any functions that a constraint doesn't need to define, don't define + * for such cases, just use NULL + * - these should be defined after all the functions have been defined, so that + * forward-definitions/prototypes don't need to be used! + * - keep this copy #if-def'd so that future constraints can get based off this + */ +#if 0 +static FModifierTypeInfo FMI_MODNAME = { + FMODIFIER_TYPE_MODNAME, /* type */ + sizeof(FMod_ModName), /* size */ + FMI_TYPE_SOME_ACTION, /* action type */ + FMI_REQUIRES_SOME_REQUIREMENT, /* requirements */ + "Modifier Name", /* name */ + "FMod_ModName", /* struct name */ + fcm_modname_free, /* free data */ + fcm_modname_relink, /* relink data */ + fcm_modname_copy, /* copy data */ + fcm_modname_new_data, /* new data */ + fcm_modname_verify, /* verify */ + fcm_modname_time, /* evaluate time */ + fcm_modname_evaluate /* evaluate */ +}; +#endif + +/* Generator F-Curve Modifier --------------------------- */ + +/* Generators available: + * 1) simple polynomial generator: + * - Exanded form - (y = C[0]*(x^(n)) + C[1]*(x^(n-1)) + ... + C[n]) + * - Factorised form - (y = (C[0][0]*x + C[0][1]) * (C[1][0]*x + C[1][1]) * ... * (C[n][0]*x + C[n][1])) + * 2) simple builin 'functions': + * of the form (y = C[0] * fn( C[1]*x + C[2] ) + C[3]) + * where fn() can be any one of: + * sin, cos, tan, ln, sqrt + * 3) expression... + */ + +static void fcm_generator_free (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* free polynomial coefficients array */ + if (data->coefficients) + MEM_freeN(data->coefficients); +} + +static void fcm_generator_copy (FModifier *fcm, FModifier *src) +{ + FMod_Generator *gen= (FMod_Generator *)fcm->data; + FMod_Generator *ogen= (FMod_Generator *)src->data; + + /* copy coefficients array? */ + if (ogen->coefficients) + gen->coefficients= MEM_dupallocN(ogen->coefficients); +} + +static void fcm_generator_new_data (void *mdata) +{ + FMod_Generator *data= (FMod_Generator *)mdata; + float *cp; + + /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */ + data->poly_order= 1; + data->arraysize= 2; + cp= data->coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs"); + cp[0] = 0; // y-offset + cp[1] = 1; // gradient +} + +static void fcm_generator_verify (FModifier *fcm) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* requirements depend on mode */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* arraysize needs to be order+1, so resize if not */ + if (data->arraysize != (data->poly_order+1)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order+1), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order+1)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order+1)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order+1; + } + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */ + { + /* arraysize needs to be 2*order, so resize if not */ + if (data->arraysize != (data->poly_order * 2)) { + float *nc; + + /* make new coefficients array, and copy over as much data as can fit */ + nc= MEM_callocN(sizeof(float)*(data->poly_order*2), "FMod_Generator_Coefs"); + + if (data->coefficients) { + if (data->arraysize > (data->poly_order * 2)) + memcpy(nc, data->coefficients, sizeof(float)*(data->poly_order * 2)); + else + memcpy(nc, data->coefficients, sizeof(float)*data->arraysize); + + /* free the old data */ + MEM_freeN(data->coefficients); + } + + /* set the new data */ + data->coefficients= nc; + data->arraysize= data->poly_order * 2; + } + } + break; + + case FCM_GENERATOR_FUNCTION: /* builtin function */ + { + /* arraysize needs to be 4*/ + if (data->arraysize != 4) { + float *nc; + + /* free the old data */ + if (data->coefficients) + MEM_freeN(data->coefficients); + + /* make new coefficients array, and init using default values */ + nc= data->coefficients= MEM_callocN(sizeof(float)*4, "FMod_Generator_Coefs"); + data->arraysize= 4; + + nc[0]= 1.0f; + nc[1]= 1.0f; + nc[2]= 0.0f; + nc[3]= 0.0f; + } + } + break; + } +} + +static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Generator *data= (FMod_Generator *)fcm->data; + + /* behaviour depends on mode + * NOTE: the data in its default state is fine too + */ + switch (data->mode) { + case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */ + { + /* we overwrite cvalue with the sum of the polynomial */ + float *powers = MEM_callocN(sizeof(float)*data->arraysize, "Poly Powers"); + float value= 0.0f; + unsigned int i; + + /* for each x^n, precalculate value based on previous one first... this should be + * faster that calling pow() for each entry + */ + for (i=0; i < data->arraysize; i++) { + /* first entry is x^0 = 1, otherwise, calculate based on previous */ + if (i) + powers[i]= powers[i-1] * evaltime; + else + powers[0]= 1; + } + + /* for each coefficient, add to value, which we'll write to *cvalue in one go */ + for (i=0; i < data->arraysize; i++) + value += data->coefficients[i] * powers[i]; + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + + /* cleanup */ + if (powers) + MEM_freeN(powers); + } + break; + + case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* factorised polynomial */ + { + float value= 1.0f, *cp=NULL; + unsigned int i; + + /* for each coefficient pair, solve for that bracket before accumulating in value by multiplying */ + for (cp=data->coefficients, i=0; (cp) && (i < data->poly_order); cp+=2, i++) + value *= (cp[0]*evaltime + cp[1]); + + /* only if something changed, write *cvalue in one go */ + if (data->poly_order) { + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + } + break; + + case FCM_GENERATOR_FUNCTION: /* builtin function */ + { + double arg= data->coefficients[1]*evaltime + data->coefficients[2]; + double (*fn)(double v) = NULL; + + /* get function pointer to the func to use: + * WARNING: must perform special argument validation hereto guard against crashes + */ + switch (data->func_type) + { + /* simple ones */ + case FCM_GENERATOR_FN_SIN: /* sine wave */ + fn= sin; + break; + case FCM_GENERATOR_FN_COS: /* cosine wave */ + fn= cos; + break; + + /* validation required */ + case FCM_GENERATOR_FN_TAN: /* tangent wave */ + { + /* check that argument is not on one of the discontinuities (i.e. 90deg, 270 deg, etc) */ + if IS_EQ(fmod((arg - M_PI_2), M_PI), 0.0) { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + else + fn= tan; + } + break; + case FCM_GENERATOR_FN_LN: /* natural log */ + { + /* check that value is greater than 1? */ + if (arg > 1.0f) { + fn= log; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + case FCM_GENERATOR_FN_SQRT: /* square root */ + { + /* no negative numbers */ + if (arg > 0.0f) { + fn= sqrt; + } + else { + if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) + *cvalue = 0.0f; /* no value possible here */ + } + } + break; + + default: + printf("Invalid Function-Generator for F-Modifier - %d \n", data->func_type); + } + + /* execute function callback to set value if appropriate */ + if (fn) { + float value= (float)(data->coefficients[0]*fn(arg) + data->coefficients[3]); + + if (data->flag & FCM_GENERATOR_ADDITIVE) + *cvalue += value; + else + *cvalue= value; + } + } + break; + +#ifndef DISABLE_PYTHON + case FCM_GENERATOR_EXPRESSION: /* py-expression */ + // TODO... + break; +#endif /* DISABLE_PYTHON */ + } +} + +static FModifierTypeInfo FMI_GENERATOR = { + FMODIFIER_TYPE_GENERATOR, /* type */ + sizeof(FMod_Generator), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_NOTHING, /* requirements */ + "Generator", /* name */ + "FMod_Generator", /* struct name */ + fcm_generator_free, /* free data */ + fcm_generator_copy, /* copy data */ + fcm_generator_new_data, /* new data */ + fcm_generator_verify, /* verify */ + NULL, /* evaluate time */ + fcm_generator_evaluate /* evaluate */ +}; + +/* Envelope F-Curve Modifier --------------------------- */ + +static void fcm_envelope_free (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* free envelope data array */ + if (env->data) + MEM_freeN(env->data); +} + +static void fcm_envelope_copy (FModifier *fcm, FModifier *src) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FMod_Envelope *oenv= (FMod_Envelope *)src->data; + + /* copy envelope data array */ + if (oenv->data) + env->data= MEM_dupallocN(oenv->data); +} + +static void fcm_envelope_new_data (void *mdata) +{ + FMod_Envelope *env= (FMod_Envelope *)mdata; + + /* set default min/max ranges */ + env->min= -1.0f; + env->max= 1.0f; +} + +static void fcm_envelope_verify (FModifier *fcm) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + + /* if the are points, perform bubble-sort on them, as user may have changed the order */ + if (env->data) { + // XXX todo... + } +} + +static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Envelope *env= (FMod_Envelope *)fcm->data; + FCM_EnvelopeData *fed, *prevfed, *lastfed; + float min=0.0f, max=0.0f, fac=0.0f; + int a; + + /* get pointers */ + if (env->data == NULL) return; + prevfed= env->data; + fed= prevfed + 1; + lastfed= prevfed + (env->totvert-1); + + /* get min/max values for envelope at evaluation time (relative to mid-value) */ + if (prevfed->time >= evaltime) { + /* before or on first sample, so just extend value */ + min= prevfed->min; + max= prevfed->max; + } + else if (lastfed->time <= evaltime) { + /* after or on last sample, so just extend value */ + min= lastfed->min; + max= lastfed->max; + } + else { + /* evaltime occurs somewhere between segments */ + // TODO: implement binary search for this to make it faster? + for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) { + /* evaltime occurs within the interval defined by these two envelope points */ + if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) { + float afac, bfac, diff; + + diff= fed->time - prevfed->time; + afac= (evaltime - prevfed->time) / diff; + bfac= (fed->time - evaltime) / diff; + + min= bfac*prevfed->min + afac*fed->min; + max= bfac*prevfed->max + afac*fed->max; + + break; + } + } + } + + /* adjust *cvalue + * - fac is the ratio of how the current y-value corresponds to the reference range + * - thus, the new value is found by mapping the old range to the new! + */ + fac= (*cvalue - (env->midval + env->min)) / (env->max - env->min); + *cvalue= min + fac*(max - min); +} + +static FModifierTypeInfo FMI_ENVELOPE = { + FMODIFIER_TYPE_ENVELOPE, /* type */ + sizeof(FMod_Envelope), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Envelope", /* name */ + "FMod_Envelope", /* struct name */ + fcm_envelope_free, /* free data */ + fcm_envelope_copy, /* copy data */ + fcm_envelope_new_data, /* new data */ + fcm_envelope_verify, /* verify */ + NULL, /* evaluate time */ + fcm_envelope_evaluate /* evaluate */ +}; + +/* Cycles F-Curve Modifier --------------------------- */ + +/* This modifier changes evaltime to something that exists within the curve's frame-range, + * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour + * is very likely to be more time-consuming than the original approach... (which was tighly integrated into + * the calculation code...). + * + * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data + * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted + * as appropriate + */ + +/* temp data used during evaluation */ +typedef struct tFCMED_Cycles { + float cycyofs; /* y-offset to apply */ +} tFCMED_Cycles; + +static void fcm_cycles_new_data (void *mdata) +{ + FMod_Cycles *data= (FMod_Cycles *)mdata; + + /* turn on cycles by default */ + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; +} + +static float fcm_cycles_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + float prevkey[2], lastkey[2], cycyofs=0.0f; + short side=0, mode=0; + int cycles=0; + + /* check if modifier is first in stack, otherwise disable ourself... */ + // FIXME... + if (fcm->prev) { + fcm->flag |= FMODIFIER_FLAG_DISABLED; + return evaltime; + } + + /* calculate new evaltime due to cyclic interpolation */ + if (fcu && fcu->bezt) { + BezTriple *prevbezt= fcu->bezt; + BezTriple *lastbezt= prevbezt + fcu->totvert-1; + + prevkey[0]= prevbezt->vec[1][0]; + prevkey[1]= prevbezt->vec[1][1]; + + lastkey[0]= lastbezt->vec[1][0]; + lastkey[1]= lastbezt->vec[1][1]; + } + else if (fcu && fcu->fpt) { + FPoint *prevfpt= fcu->fpt; + FPoint *lastfpt= prevfpt + fcu->totvert-1; + + prevkey[0]= prevfpt->vec[0]; + prevkey[1]= prevfpt->vec[1]; + + lastkey[0]= lastfpt->vec[0]; + lastkey[1]= lastfpt->vec[1]; + } + else + return evaltime; + + /* check if modifier will do anything + * 1) if in data range, definitely don't do anything + * 2) if before first frame or after last frame, make sure some cycling is in use + */ + if (evaltime < prevkey[0]) { + if (data->before_mode) { + side= -1; + mode= data->before_mode; + cycles= data->before_cycles; + } + } + else if (evaltime > lastkey[0]) { + if (data->after_mode) { + side= 1; + mode= data->after_mode; + cycles= data->after_cycles; + } + } + if ELEM(0, side, mode) + return evaltime; + + /* find relative place within a cycle */ + { + float cycdx=0, cycdy=0, ofs=0; + float cycle= 0; + + /* ofs is start frame of cycle */ + ofs= prevkey[0]; + + /* calculate period and amplitude (total height) of a cycle */ + cycdx= lastkey[0] - prevkey[0]; + cycdy= lastkey[1] - prevkey[1]; + + /* check if cycle is infinitely small, to be point of being impossible to use */ + if (cycdx == 0) + return evaltime; + + /* calculate the 'number' of the cycle */ + cycle= ((float)side * (evaltime - ofs) / cycdx); + + /* check that cyclic is still enabled for the specified time */ + if (cycles == 0) { + /* catch this case so that we don't exit when we have cycles=0 + * as this indicates infinite cycles... + */ + } + else if (cycle > (cycles+1)) { + /* we are too far away from range to evaluate + * TODO: but we should still hold last value... + */ + return evaltime; + } + + /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + cycyofs = (float)floor((evaltime - ofs) / cycdx); + cycyofs *= cycdy; + } + + /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ + if ((mode == FCM_EXTRAPOLATE_MIRROR) && ((int)(cycle) % 2)) { + /* when 'mirror' option is used and cycle number is odd, this cycle is played in reverse + * - for 'before' extrapolation, we need to flip in a different way, otherwise values past + * then end of the curve get referenced (result of fmod will be negative, and with different phase) + */ + if (side < 0) + evaltime= (float)(prevkey[0] - fmod(evaltime-ofs, cycdx)); + else + evaltime= (float)(lastkey[0] - fmod(evaltime-ofs, cycdx)); + } + else { + /* the cycle is played normally... */ + evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); + } + if (evaltime < ofs) evaltime += cycdx; + } + + /* store temp data if needed */ + if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) { + tFCMED_Cycles *edata; + + /* for now, this is just a float, but we could get more stuff... */ + fcm->edata= edata= MEM_callocN(sizeof(tFCMED_Cycles), "tFCMED_Cycles"); + edata->cycyofs= cycyofs; + } + + /* return the new frame to evaluate */ + return evaltime; +} + +static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + tFCMED_Cycles *edata= (tFCMED_Cycles *)fcm->edata; + + /* use temp data */ + if (edata) { + /* add cyclic offset - no need to check for now, otherwise the data wouldn't exist! */ + *cvalue += edata->cycyofs; + + /* free temp data */ + MEM_freeN(edata); + fcm->edata= NULL; + } +} + +static FModifierTypeInfo FMI_CYCLES = { + FMODIFIER_TYPE_CYCLES, /* type */ + sizeof(FMod_Cycles), /* size */ + FMI_TYPE_EXTRAPOLATION, /* action type */ + FMI_REQUIRES_ORIGINAL_DATA, /* requirements */ + "Cycles", /* name */ + "FMod_Cycles", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_cycles_new_data, /* new data */ + NULL /*fcm_cycles_verify*/, /* verify */ + fcm_cycles_time, /* evaluate time */ + fcm_cycles_evaluate /* evaluate */ +}; + +/* Noise F-Curve Modifier --------------------------- */ + +static void fcm_noise_new_data (void *mdata) +{ + FMod_Noise *data= (FMod_Noise *)mdata; + + /* defaults */ + data->size= 1.0f; + data->strength= 1.0f; + data->phase= 1.0f; + data->depth = 0; + data->modification = FCM_NOISE_MODIF_REPLACE; +} + +static void fcm_noise_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Noise *data= (FMod_Noise *)fcm->data; + float noise; + + noise = BLI_turbulence(data->size, evaltime, data->phase, 0.f, data->depth); + + switch (data->modification) { + case FCM_NOISE_MODIF_ADD: + *cvalue= *cvalue + noise * data->strength; + break; + case FCM_NOISE_MODIF_SUBTRACT: + *cvalue= *cvalue - noise * data->strength; + break; + case FCM_NOISE_MODIF_MULTIPLY: + *cvalue= *cvalue * noise * data->strength; + break; + case FCM_NOISE_MODIF_REPLACE: + default: + *cvalue= *cvalue + (noise - 0.5f) * data->strength; + break; + } +} + +static FModifierTypeInfo FMI_NOISE = { + FMODIFIER_TYPE_NOISE, /* type */ + sizeof(FMod_Noise), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Noise", /* name */ + "FMod_Noise", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + fcm_noise_new_data, /* new data */ + NULL /*fcm_noise_verify*/, /* verify */ + NULL, /* evaluate time */ + fcm_noise_evaluate /* evaluate */ +}; + +/* Filter F-Curve Modifier --------------------------- */ + +#if 0 // XXX not yet implemented +static FModifierTypeInfo FMI_FILTER = { + FMODIFIER_TYPE_FILTER, /* type */ + sizeof(FMod_Filter), /* size */ + FMI_TYPE_REPLACE_VALUES, /* action type */ + 0, /* requirements */ + "Filter", /* name */ + "FMod_Filter", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL /*fcm_filter_verify*/, /* verify */ + NULL, /* evlauate time */ + fcm_filter_evaluate /* evaluate */ +}; +#endif // XXX not yet implemented + + +/* Python F-Curve Modifier --------------------------- */ + +static void fcm_python_free (FModifier *fcm) +{ + FMod_Python *data= (FMod_Python *)fcm->data; + + /* id-properties */ + IDP_FreeProperty(data->prop); + MEM_freeN(data->prop); +} + +static void fcm_python_new_data (void *mdata) +{ + FMod_Python *data= (FMod_Python *)mdata; + + /* everything should be set correctly by calloc, except for the prop->type constant.*/ + data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps"); + data->prop->type = IDP_GROUP; +} + +static void fcm_python_copy (FModifier *fcm, FModifier *src) +{ + FMod_Python *pymod = (FMod_Python *)fcm->data; + FMod_Python *opymod = (FMod_Python *)src->data; + + pymod->prop = IDP_CopyProperty(opymod->prop); +} + +static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ +#ifndef DISABLE_PYTHON + //FMod_Python *data= (FMod_Python *)fcm->data; + + /* FIXME... need to implement this modifier... + * It will need it execute a script using the custom properties + */ +#endif /* DISABLE_PYTHON */ +} + +static FModifierTypeInfo FMI_PYTHON = { + FMODIFIER_TYPE_PYTHON, /* type */ + sizeof(FMod_Python), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Python", /* name */ + "FMod_Python", /* struct name */ + fcm_python_free, /* free data */ + fcm_python_copy, /* copy data */ + fcm_python_new_data, /* new data */ + NULL /*fcm_python_verify*/, /* verify */ + NULL /*fcm_python_time*/, /* evaluate time */ + fcm_python_evaluate /* evaluate */ +}; + + +/* Limits F-Curve Modifier --------------------------- */ + +static float fcm_limits_time (FCurve *fcu, FModifier *fcm, float cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* check for the time limits */ + if ((data->flag & FCM_LIMIT_XMIN) && (evaltime < data->rect.xmin)) + return data->rect.xmin; + if ((data->flag & FCM_LIMIT_XMAX) && (evaltime > data->rect.xmax)) + return data->rect.xmax; + + /* modifier doesn't change time */ + return evaltime; +} + +static void fcm_limits_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime) +{ + FMod_Limits *data= (FMod_Limits *)fcm->data; + + /* value limits now */ + if ((data->flag & FCM_LIMIT_YMIN) && (*cvalue < data->rect.ymin)) + *cvalue= data->rect.ymin; + if ((data->flag & FCM_LIMIT_YMAX) && (*cvalue > data->rect.ymax)) + *cvalue= data->rect.ymax; +} + +static FModifierTypeInfo FMI_LIMITS = { + FMODIFIER_TYPE_LIMITS, /* type */ + sizeof(FMod_Limits), /* size */ + FMI_TYPE_GENERATE_CURVE, /* action type */ /* XXX... err... */ + FMI_REQUIRES_RUNTIME_CHECK, /* requirements */ + "Limits", /* name */ + "FMod_Limits", /* struct name */ + NULL, /* free data */ + NULL, /* copy data */ + NULL, /* new data */ + NULL, /* verify */ + fcm_limits_time, /* evaluate time */ + fcm_limits_evaluate /* evaluate */ +}; + +/* F-Curve Modifier API --------------------------- */ +/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out + * and operations that involve F-Curve modifier specific code. + */ + +/* These globals only ever get directly accessed in this file */ +static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES]; +static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */ + +/* This function only gets called when FMI_INIT is non-zero */ +static void fmods_init_typeinfo () +{ + fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */ + fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */ + fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */ + fmodifiersTypeInfo[3]= &FMI_CYCLES; /* Cycles F-Curve Modifier */ + fmodifiersTypeInfo[4]= &FMI_NOISE; /* Apply-Noise F-Curve Modifier */ + fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented + fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */ + fmodifiersTypeInfo[7]= &FMI_LIMITS; /* Limits F-Curve Modifier */ +} + +/* This function should be used for getting the appropriate type-info when only + * a F-Curve modifier type is known + */ +FModifierTypeInfo *get_fmodifier_typeinfo (int type) +{ + /* initialise the type-info list? */ + if (FMI_INIT) { + fmods_init_typeinfo(); + FMI_INIT = 0; + } + + /* only return for valid types */ + if ( (type >= FMODIFIER_TYPE_NULL) && + (type <= FMODIFIER_NUM_TYPES ) ) + { + /* there shouldn't be any segfaults here... */ + return fmodifiersTypeInfo[type]; + } + else { + printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type); + } + + return NULL; +} + +/* This function should always be used to get the appropriate type-info, as it + * has checks which prevent segfaults in some weird cases. + */ +FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm) +{ + /* only return typeinfo for valid modifiers */ + if (fcm) + return get_fmodifier_typeinfo(fcm->type); + else + return NULL; +} + +/* API --------------------------- */ + +/* Add a new F-Curve Modifier to the given F-Curve of a certain type */ +FModifier *fcurve_add_modifier (FCurve *fcu, int type) +{ + FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type); + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, fcu, fmi) + return NULL; + + /* special checks for whether modifier can be added */ + if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) { + /* cycles modifier must be first in stack, so for now, don't add if it can't be */ + // TODO: perhaps there is some better way, but for now, + printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n"); + return NULL; + } + + /* add modifier itself */ + fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier"); + fcm->type = type; + fcm->flag = FMODIFIER_FLAG_EXPANDED; + BLI_addtail(&fcu->modifiers, fcm); + + /* add modifier's data */ + fcm->data= MEM_callocN(fmi->size, fmi->structName); + + /* init custom settings if necessary */ + if (fmi->new_data) + fmi->new_data(fcm->data); + + /* return modifier for further editing */ + return fcm; +} + +/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */ +void fcurve_copy_modifiers (ListBase *dst, ListBase *src) +{ + FModifier *fcm, *srcfcm; + + if ELEM(NULL, dst, src) + return; + + dst->first= dst->last= NULL; + BLI_duplicatelist(dst, src); + + for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* make a new copy of the F-Modifier's data */ + fcm->data = MEM_dupallocN(fcm->data); + + /* only do specific constraints if required */ + if (fmi && fmi->copy_data) + fmi->copy_data(fcm, srcfcm); + } +} + +/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */ +void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm) +{ + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* sanity check */ + if (fcm == NULL) + return; + + /* free modifier's special data (stored inside fcm->data) */ + if (fcm->data) { + if (fmi && fmi->free_data) + fmi->free_data(fcm); + + /* free modifier's data (fcm->data) */ + MEM_freeN(fcm->data); + } + + /* remove modifier from stack */ + if (fcu) + BLI_freelinkN(&fcu->modifiers, fcm); + else { + // XXX this case can probably be removed some day, as it shouldn't happen... + printf("fcurve_remove_modifier() - no fcurve \n"); + MEM_freeN(fcm); + } +} + +/* Remove all of a given F-Curve's modifiers */ +void fcurve_free_modifiers (FCurve *fcu) +{ + FModifier *fcm, *fmn; + + /* sanity check */ + if (fcu == NULL) + return; + + /* free each modifier in order - modifier is unlinked from list and freed */ + for (fcm= fcu->modifiers.first; fcm; fcm= fmn) { + fmn= fcm->next; + fcurve_remove_modifier(fcu, fcm); + } +} + +/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined + * by start and end (inclusive). + */ +void fcurve_bake_modifiers (FCurve *fcu, int start, int end) +{ + ChannelDriver *driver; + + /* sanity checks */ + // TODO: make these tests report errors using reports not printf's + if ELEM(NULL, fcu, fcu->modifiers.first) { + printf("Error: No F-Curve with F-Curve Modifiers to Bake\n"); + return; + } + + /* temporarily, disable driver while we sample, so that they don't influence the outcome */ + driver= fcu->driver; + fcu->driver= NULL; + + /* bake the modifiers, by sampling the curve at each frame */ + fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve); + + /* free the modifiers now */ + fcurve_free_modifiers(fcu); + + /* restore driver */ + fcu->driver= driver; +} + +/* Find the active F-Curve Modifier */ +FModifier *fcurve_find_active_modifier (FCurve *fcu) +{ + FModifier *fcm; + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->modifiers.first) + return NULL; + + /* loop over modifiers until 'active' one is found */ + for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { + if (fcm->flag & FMODIFIER_FLAG_ACTIVE) + return fcm; + } + + /* no modifier is active */ + return NULL; +} + +/* Set the active F-Curve Modifier */ +void fcurve_set_active_modifier (FCurve *fcu, FModifier *fcm) +{ + FModifier *fm; + + /* sanity checks */ + if ELEM(NULL, fcu, fcu->modifiers.first) + return; + + /* deactivate all, and set current one active */ + for (fm= fcu->modifiers.first; fm; fm= fm->next) + fm->flag &= ~FMODIFIER_FLAG_ACTIVE; + + /* make given modifier active */ + if (fcm) + fcm->flag |= FMODIFIER_FLAG_ACTIVE; +} + +/* ***************************** F-Curve - Evaluation ********************************* */ + +/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") + * Note: this is also used for drivers + */ +float evaluate_fcurve (FCurve *fcu, float evaltime) +{ + FModifier *fcm; + float cvalue= 0.0f; + float devaltime; + + /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime" + * since drivers essentially act as alternative input (i.e. in place of 'time') for F-Curves + * - this value will also be returned as the value of the 'curve', if there are no keyframes + */ + if (fcu->driver) { + /* evaltime now serves as input for the curve */ + evaltime= cvalue= evaluate_driver(fcu->driver, evaltime); + } + + /* evaluate time modifications imposed by some F-Curve Modifiers + * - this step acts as an optimisation to prevent the F-Curve stack being evaluated + * several times by modifiers requesting the time be modified, as the final result + * would have required using the modified time + * - modifiers only ever recieve the unmodified time, as subsequent modifiers should be + * working on the 'global' result of the modified curve, not some localised segment, + * so nevaltime gets set to whatever the last time-modifying modifier likes... + * - we start from the end of the stack, as only the last one matters for now + */ + devaltime= evaltime; + + for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier_time) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + devaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime); + break; + } + } + + /* evaluate curve-data + * - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying + * F-Curve modifier on the stack requested the curve to be evaluated at + */ + if (fcu->bezt) + cvalue= fcurve_eval_keyframes(fcu, fcu->bezt, devaltime); + else if (fcu->fpt) + cvalue= fcurve_eval_samples(fcu, fcu->fpt, devaltime); + + /* evaluate modifiers */ + for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) { + FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); + + /* only evaluate if there's a callback for this */ + // TODO: implement the 'influence' control feature... + if (fmi && fmi->evaluate_modifier) { + if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) + fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime); + } + } + + /* if curve can only have integral values, perform truncation (i.e. drop the decimal part) + * here so that the curve can be sampled correctly + */ + if (fcu->flag & FCURVE_INT_VALUES) + cvalue= (float)((int)cvalue); + + /* return evaluated value */ + return cvalue; +} + +/* Calculate the value of the given F-Curve at the given frame, and set its curval */ +// TODO: will this be necessary? +void calculate_fcurve (FCurve *fcu, float ctime) +{ + /* calculate and set curval (evaluates driver too) */ + fcu->curval= evaluate_fcurve(fcu, ctime); +} + diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 29c4e0f2fb5..9eefd48cae4 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -52,7 +52,6 @@ // headers for fluidsim bobj meshes #include <stdlib.h> #include "LBM_fluidsim.h" -#include "elbeem.h" #include <zlib.h> #include <string.h> #include <stdio.h> @@ -167,14 +166,14 @@ void fluidsim_free(FluidsimModifierData *fluidmd) return; } -DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Scene *scene, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { #ifndef DISABLE_ELBEEM DerivedMesh *result = NULL; int framenr; FluidsimSettings *fss = NULL; - framenr= (int)G.scene->r.cfra; + framenr= (int)scene->r.cfra; // only handle fluidsim domains if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN)) @@ -396,7 +395,7 @@ static DerivedMesh *fluidsim_read_obj(char *filename) DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { int displaymode = 0; - int curFrame = framenr - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */ + int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */ char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR]; FluidsimSettings *fss = fluidmd->fss; DerivedMesh *dm = NULL; @@ -598,7 +597,7 @@ void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4], // file handling //------------------------------------------------------------------------------- -void initElbeemMesh(struct Object *ob, +void initElbeemMesh(struct Scene *scene, struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex) @@ -610,7 +609,7 @@ void initElbeemMesh(struct Object *ob, float *verts; int *tris; - dm = mesh_create_derived_index_render(ob, CD_MASK_BAREMESH, modifierIndex); + dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex); //dm = mesh_create_derived_no_deform(ob,NULL); mvert = dm->getVertArray(dm); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 52275e507dd..c3cf6e06c09 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -53,7 +53,6 @@ #include "DNA_scene_types.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" #include "BKE_packedFile.h" @@ -66,9 +65,7 @@ #include "BKE_curve.h" #include "BKE_displist.h" -#define callocstructN(x,y,name) (x*)MEM_callocN((y)* sizeof(x),name) - -struct SelBox *selboxes= NULL; +static ListBase ttfdata= {NULL, NULL}; /* UTF-8 <-> wchar transformations */ void @@ -270,22 +267,46 @@ static PackedFile *get_builtin_packedfile(void) } } -static VFontData *vfont_get_data(VFont *vfont) +void free_ttfont(void) +{ + struct TmpFont *tf; + + tf= ttfdata.first; + while(tf) { + freePackedFile(tf->pf); + tf->pf= NULL; + tf->vfont= NULL; + tf= tf->next; + } + BLI_freelistN(&ttfdata); +} + +struct TmpFont *vfont_find_tmpfont(VFont *vfont) { struct TmpFont *tmpfnt = NULL; - PackedFile *tpf; if(vfont==NULL) return NULL; // Try finding the font from font list - tmpfnt = G.ttfdata.first; - + tmpfnt = ttfdata.first; while(tmpfnt) { if(tmpfnt->vfont == vfont) break; tmpfnt = tmpfnt->next; } + return tmpfnt; +} + +static VFontData *vfont_get_data(VFont *vfont) +{ + struct TmpFont *tmpfnt = NULL; + PackedFile *tpf; + + if(vfont==NULL) return NULL; + + // Try finding the font from font list + tmpfnt = vfont_find_tmpfont(vfont); // And then set the data if (!vfont->data) { @@ -309,7 +330,7 @@ static VFontData *vfont_get_data(VFont *vfont) tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); tmpfnt->pf= tpf; tmpfnt->vfont= vfont; - BLI_addtail(&G.ttfdata, tmpfnt); + BLI_addtail(&ttfdata, tmpfnt); } } else { pf= newPackedFile(vfont->name); @@ -322,7 +343,7 @@ static VFontData *vfont_get_data(VFont *vfont) tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); tmpfnt->pf= tpf; tmpfnt->vfont= vfont; - BLI_addtail(&G.ttfdata, tmpfnt); + BLI_addtail(&ttfdata, tmpfnt); } } if(!pf) { @@ -334,11 +355,7 @@ static VFontData *vfont_get_data(VFont *vfont) } if (pf) { -#ifdef WITH_FREETYPE2 vfont->data= BLI_vfontdata_from_freetypefont(pf); -#else - vfont->data= BLI_vfontdata_from_psfont(pf); -#endif if (pf != vfont->packedfile) { freePackedFile(pf); } @@ -376,15 +393,8 @@ VFont *load_vfont(char *name) if (pf) { VFontData *vfd; - - waitcursor(1); -#ifdef WITH_FREETYPE2 vfd= BLI_vfontdata_from_freetypefont(pf); -#else - vfd= BLI_vfontdata_from_psfont(pf); -#endif - if (vfd) { vfont = alloc_libblock(&G.main->vfont, ID_VF, filename); vfont->data = vfd; @@ -402,7 +412,7 @@ VFont *load_vfont(char *name) tmpfnt= (struct TmpFont *) MEM_callocN(sizeof(struct TmpFont), "temp_font"); tmpfnt->pf= tpf; tmpfnt->vfont= vfont; - BLI_addtail(&G.ttfdata, tmpfnt); + BLI_addtail(&ttfdata, tmpfnt); } } @@ -411,7 +421,7 @@ VFont *load_vfont(char *name) freePackedFile(pf); } - waitcursor(0); + //XXX waitcursor(0); } return vfont; @@ -431,6 +441,17 @@ static VFont *which_vfont(Curve *cu, CharInfo *info) } } +VFont *get_builtin_font(void) +{ + VFont *vf; + + for (vf= G.main->vfont.first; vf; vf= vf->id.next) + if (BLI_streq(vf->name, "<builtin>")) + return vf; + + return load_vfont("<builtin>"); +} + static void build_underline(Curve *cu, float x1, float y1, float x2, float y2, int charidx, short mat_nr) { Nurb *nu2; @@ -599,13 +620,11 @@ static void buildchar(Curve *cu, unsigned long character, CharInfo *info, float } } -int getselection(int *start, int *end) +int BKE_font_getselection(Object *ob, int *start, int *end) { - Curve *cu; - - if (G.obedit==NULL || G.obedit->type != OB_FONT) return 0; + Curve *cu= ob->data; - cu= G.obedit->data; + if (cu->editfont==NULL || ob->type != OB_FONT) return 0; if (cu->selstart == 0) return 0; if (cu->selstart <= cu->selend) { @@ -620,30 +639,23 @@ int getselection(int *start, int *end) } } -struct chartrans *text_to_curve(Object *ob, int mode) +struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) { VFont *vfont, *oldvfont; VFontData *vfd= NULL; - Curve *cu, *cucu; - struct chartrans *chartransdata=NULL, *ct; - float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy; - float cmat[3][3], timeofs, si, co, sizefac; - float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4; - int i, slen, oldflag, j; - short cnr=0, lnr=0, wsnr= 0; - wchar_t *mem, *tmp, ascii; - int outta; - float vecyo[3], curofs; - CharInfo *info; - float wsfac; - float ulwidth, uloverlap; + Curve *cu; + CharInfo *info, *custrinfo; TextBox *tb; + VChar *che; + struct chartrans *chartransdata=NULL, *ct; + float *f, xof, yof, xtrax, linedist, *linedata, *linedata2, *linedata3, *linedata4; + float twidth, maxlen= 0; + int i, slen, j; int curbox; int selstart, selend; - SelBox *sb= NULL; /* to please gcc */ - VChar *che; - float twidth; int utf8len; + short cnr=0, lnr=0, wsnr= 0; + wchar_t *mem, *tmp, ascii; /* renark: do calculations including the trailing '\0' of a string because the cursor can be at that location */ @@ -653,9 +665,9 @@ struct chartrans *text_to_curve(Object *ob, int mode) // Set font data cu= (Curve *) ob->data; vfont= cu->vfont; - - if(cu->str == 0) return 0; - if(vfont == 0) return 0; + + if(cu->str == NULL) return 0; + if(vfont == NULL) return 0; // Create unicode string utf8len = utf8slen(cu->str); @@ -666,19 +678,23 @@ struct chartrans *text_to_curve(Object *ob, int mode) // Count the wchar_t string length slen = wcslen(mem); - if (cu->ulheight == 0.0) cu->ulheight = 0.05; - if (cu->strinfo==NULL) { /* old file */ + if (cu->ulheight == 0.0) + cu->ulheight = 0.05; + + if (cu->strinfo==NULL) /* old file */ cu->strinfo = MEM_callocN((slen+1) * sizeof(CharInfo), "strinfo compat"); - } - if (cu->tb==NULL) { + + custrinfo= cu->strinfo; + if (cu->editfont) + custrinfo= cu->editfont->textbufinfo; + + if (cu->tb==NULL) cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "TextBox compat"); - } vfd= vfont_get_data(vfont); /* The VFont Data can not be found */ - if(!vfd) - { + if(!vfd) { if(mem) MEM_freeN(mem); return 0; @@ -704,12 +720,12 @@ struct chartrans *text_to_curve(Object *ob, int mode) oldvfont = NULL; - for (i=0; i<slen; i++) cu->strinfo[i].flag &= ~CU_WRAP; + for (i=0; i<slen; i++) custrinfo[i].flag &= ~CU_WRAP; - if (selboxes) MEM_freeN(selboxes); - selboxes = NULL; - if (getselection(&selstart, &selend)) - selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes"); + if (cu->selboxes) MEM_freeN(cu->selboxes); + cu->selboxes = NULL; + if (BKE_font_getselection(ob, &selstart, &selend)) + cu->selboxes = MEM_callocN((selend-selstart+1)*sizeof(SelBox), "font selboxes"); tb = &(cu->tb[0]); curbox= 0; @@ -718,40 +734,37 @@ struct chartrans *text_to_curve(Object *ob, int mode) // Characters in the list che = vfd->characters.first; ascii = mem[i]; - info = &(cu->strinfo[i]); + info = &(custrinfo[i]); vfont = which_vfont(cu, info); if(vfont==NULL) break; // Find the character - while(che) - { + while(che) { if(che->index == ascii) break; che = che->next; } -#ifdef WITH_FREETYPE2 - // The character wasn't in the current curve base so load it - // But if the font is <builtin> then do not try loading since whole font is in the memory already - if(che == NULL && strcmp(vfont->name, "<builtin>")) - { + /* + * The character wasn't in the current curve base so load it + * But if the font is <builtin> then do not try loading since + * whole font is in the memory already + */ + if(che == NULL && strcmp(vfont->name, "<builtin>")) { BLI_vfontchar_from_freetypefont(vfont, ascii); } - // Try getting the character again from the list + /* Try getting the character again from the list */ che = vfd->characters.first; - while(che) - { + while(che) { if(che->index == ascii) break; che = che->next; } -#endif /* No VFont found */ - if (vfont==0) - { + if (vfont==0) { if(mem) MEM_freeN(mem); MEM_freeN(chartransdata); @@ -764,8 +777,7 @@ struct chartrans *text_to_curve(Object *ob, int mode) } /* VFont Data for VFont couldn't be found */ - if (!vfd) - { + if (!vfd) { if(mem) MEM_freeN(mem); MEM_freeN(chartransdata); @@ -774,13 +786,9 @@ struct chartrans *text_to_curve(Object *ob, int mode) // The character wasn't found, propably ascii = 0, then the width shall be 0 as well if(!che) - { twidth = 0; - } else - { twidth = che->width; - } // Calculate positions if((tb->w != 0.0) && (ct->dobreak==0) && ((xof-(tb->x/cu->fsize)+twidth)*cu->fsize) > tb->w) { @@ -794,13 +802,13 @@ struct chartrans *text_to_curve(Object *ob, int mode) i = j-1; xof = ct->xof; ct[1].dobreak = 1; - cu->strinfo[i+1].flag |= CU_WRAP; + custrinfo[i+1].flag |= CU_WRAP; goto makebreak; } if (chartransdata[j].dobreak) { // fprintf(stderr, "word too long: %c%c%c...\n", mem[j], mem[j+1], mem[j+2]); ct->dobreak= 1; - cu->strinfo[i+1].flag |= CU_WRAP; + custrinfo[i+1].flag |= CU_WRAP; ct -= 1; cnr -= 1; i--; @@ -843,6 +851,8 @@ struct chartrans *text_to_curve(Object *ob, int mode) wsnr= 0; } else if(ascii==9) { /* TAB */ + float tabfac; + ct->xof= xof; ct->yof= yof; ct->linenr= lnr; @@ -853,13 +863,16 @@ struct chartrans *text_to_curve(Object *ob, int mode) xof= cu->xof+tabfac; } else { + SelBox *sb= NULL; + float wsfac; + ct->xof= xof; ct->yof= yof; ct->linenr= lnr; ct->charnr= cnr++; - if (selboxes && (i>=selstart) && (i<=selend)) { - sb = &(selboxes[i-selstart]); + if (cu->selboxes && (i>=selstart) && (i<=selend)) { + sb = &(cu->selboxes[i-selstart]); sb->y = yof*cu->fsize-linedist*cu->fsize*0.1; sb->h = linedist*cu->fsize; sb->w = xof*cu->fsize; @@ -868,25 +881,23 @@ struct chartrans *text_to_curve(Object *ob, int mode) if (ascii==32) { wsfac = cu->wordspace; wsnr++; - } else wsfac = 1.0; + } + else wsfac = 1.0; + // Set the width of the character if(!che) - { twidth = 0; - } - else - { + else twidth = che->width; - } + xof += (twidth*wsfac*(1.0+(info->kern/40.0)) ) + xtrax; - if (selboxes && (i>=selstart) && (i<=selend)) sb->w = (xof*cu->fsize) - sb->w; + if (sb) + sb->w = (xof*cu->fsize) - sb->w; } ct++; } - - cu->lines= 1; ct= chartransdata; tmp = mem; @@ -928,9 +939,9 @@ struct chartrans *text_to_curve(Object *ob, int mode) // } ct++; } - } else if((cu->spacemode==CU_JUSTIFY) && - (cu->tb[0].w != 0.0)) { - curofs= 0; + } + else if((cu->spacemode==CU_JUSTIFY) && (cu->tb[0].w != 0.0)) { + float curofs= 0.0f; for (i=0; i<=slen; i++) { for (j=i; (mem[j]) && (mem[j]!='\n') && (mem[j]!='\r') && (chartransdata[j].dobreak==0) && (j<slen); j++); @@ -947,14 +958,17 @@ struct chartrans *text_to_curve(Object *ob, int mode) /* TEXT ON CURVE */ if(cu->textoncurve) { - cucu= cu->textoncurve->data; + Curve *cucu= cu->textoncurve->data; + int oldflag= cucu->flag; - oldflag= cucu->flag; cucu->flag |= (CU_PATH+CU_FOLLOW); - if(cucu->path==NULL) makeDispListCurveTypes(cu->textoncurve, 0); + if(cucu->path==NULL) makeDispListCurveTypes(scene, cu->textoncurve, 0); if(cucu->path) { - float imat[4][4], imat3[3][3]; + float distfac, imat[4][4], imat3[3][3], cmat[3][3]; + float minx, maxx, miny, maxy; + float timeofs, sizefac; + Mat4Invert(imat, ob->obmat); Mat3CpyMat4(imat3, imat); @@ -999,27 +1013,24 @@ struct chartrans *text_to_curve(Object *ob, int mode) ct= chartransdata; for (i=0; i<=slen; i++, ct++) { + float ctime, dtime, vec[4], tvec[4], rotvec[3]; + float si, co; /* rotate around center character */ ascii = mem[i]; // Find the character che = vfd->characters.first; - while(che) - { + while(che) { if(che->index == ascii) break; che = che->next; } if(che) - { twidth = che->width; - } else - { twidth = 0; - } dtime= distfac*0.35f*twidth; /* why not 0.5? */ dtime= distfac*0.5f*twidth; /* why not 0.5? */ @@ -1049,12 +1060,12 @@ struct chartrans *text_to_curve(Object *ob, int mode) } } - if (selboxes) { + if (cu->selboxes) { ct= chartransdata; for (i=0; i<=selend; i++, ct++) { if (i>=selstart) { - selboxes[i-selstart].x = ct->xof*cu->fsize; - selboxes[i-selstart].y = ct->yof*cu->fsize; + cu->selboxes[i-selstart].x = ct->xof*cu->fsize; + cu->selboxes[i-selstart].y = ct->yof*cu->fsize; } } } @@ -1090,12 +1101,14 @@ struct chartrans *text_to_curve(Object *ob, int mode) } /* cursor first */ - if(ob==G.obedit) { + if(cu->editfont) { + float si, co; + ct= chartransdata+cu->pos; si= (float)sin(ct->rot); co= (float)cos(ct->rot); - f= G.textcurs[0]; + f= cu->editfont->textcurs[0]; f[0]= cu->fsize*(-0.1f*co + ct->xof); f[1]= cu->fsize*(0.1f*si + ct->yof); @@ -1125,57 +1138,60 @@ struct chartrans *text_to_curve(Object *ob, int mode) if(mode==0) { /* make nurbdata */ unsigned long cha; - + freeNurblist(&cu->nurb); ct= chartransdata; if (cu->sepchar==0) { - for (i= 0; i<slen; i++) { - cha = (unsigned long) mem[i]; - info = &(cu->strinfo[i]); - if (info->mat_nr > (ob->totcol)) { - /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ - info->mat_nr = 0; - } + for (i= 0; i<slen; i++) { + cha = (uintptr_t) mem[i]; + info = &(cu->strinfo[i]); + if (info->mat_nr > (ob->totcol)) { + /* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */ + info->mat_nr = 0; + } // We do not want to see any character for \n or \r if(cha != '\n' && cha != '\r') buildchar(cu, cha, info, ct->xof, ct->yof, ct->rot, i); + if ((info->flag & CU_UNDERLINE) && (cu->textoncurve == NULL) && (cha != '\n') && (cha != '\r')) { - uloverlap = 0; + float ulwidth, uloverlap= 0.0f; + if ( (i<(slen-1)) && (mem[i+1] != '\n') && (mem[i+1] != '\r') && - ((mem[i+1] != ' ') || (cu->strinfo[i+1].flag & CU_UNDERLINE)) && ((cu->strinfo[i+1].flag & CU_WRAP)==0) - ) { + ((mem[i+1] != ' ') || (custrinfo[i+1].flag & CU_UNDERLINE)) && ((custrinfo[i+1].flag & CU_WRAP)==0) + ) { uloverlap = xtrax + 0.1; } // Find the character, the characters has to be in the memory already // since character checking has been done earlier already. che = vfd->characters.first; - while(che) - { + while(che) { if(che->index == cha) break; che = che->next; } - + if(!che) twidth =0; else twidth=che->width; ulwidth = cu->fsize * ((twidth* (1.0+(info->kern/40.0)))+uloverlap); build_underline(cu, ct->xof*cu->fsize, ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize, - ct->xof*cu->fsize + ulwidth, - ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize, - i, info->mat_nr); + ct->xof*cu->fsize + ulwidth, + ct->yof*cu->fsize + (cu->ulpos-0.05)*cu->fsize - cu->ulheight*cu->fsize, + i, info->mat_nr); } - ct++; - } + ct++; + } } else { - outta = 0; - for (i= 0; (i<slen) && (outta==0); i++) { - ascii = mem[i]; - info = &(cu->strinfo[i]); + int outta = 0; + for (i= 0; (i<slen) && (outta==0); i++) { + ascii = mem[i]; + info = &(custrinfo[i]); if (cu->sepchar == (i+1)) { + float vecyo[3]; + mem[0] = ascii; mem[1] = 0; - cu->strinfo[0]= *info; + custrinfo[0]= *info; cu->pos = 1; cu->len = 1; vecyo[0] = ct->xof; @@ -1186,10 +1202,10 @@ struct chartrans *text_to_curve(Object *ob, int mode) outta = 1; cu->sepchar = 0; } - ct++; + ct++; + } } } - } if(mode==FO_DUPLI) { MEM_freeN(mem); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c new file mode 100644 index 00000000000..6086aa58d40 --- /dev/null +++ b/source/blender/blenkernel/intern/gpencil.c @@ -0,0 +1,516 @@ +/** + * $Id: gpencil.c 19758 2009-04-16 13:10:08Z aligorith $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008, Blender Foundation + * This is a new part of Blender + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "DNA_listBase.h" +#include "DNA_gpencil_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_vec_types.h" + +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_global.h" +#include "BKE_gpencil.h" +#include "BKE_image.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_utildefines.h" + + +/* ************************************************** */ +/* GENERAL STUFF */ + +/* --------- Memory Management ------------ */ + +/* Free strokes belonging to a gp-frame */ +void free_gpencil_strokes (bGPDframe *gpf) +{ + bGPDstroke *gps, *gpsn; + + /* error checking */ + if (gpf == NULL) return; + + /* free strokes */ + for (gps= gpf->strokes.first; gps; gps= gpsn) { + gpsn= gps->next; + + /* free stroke memory arrays, then stroke itself */ + if (gps->points) MEM_freeN(gps->points); + BLI_freelinkN(&gpf->strokes, gps); + } +} + +/* Free all of a gp-layer's frames */ +void free_gpencil_frames (bGPDlayer *gpl) +{ + bGPDframe *gpf, *gpfn; + + /* error checking */ + if (gpl == NULL) return; + + /* free frames */ + for (gpf= gpl->frames.first; gpf; gpf= gpfn) { + gpfn= gpf->next; + + /* free strokes and their associated memory */ + free_gpencil_strokes(gpf); + BLI_freelinkN(&gpl->frames, gpf); + } +} + +/* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */ +void free_gpencil_layers (ListBase *list) +{ + bGPDlayer *gpl, *gpln; + + /* error checking */ + if (list == NULL) return; + + /* delete layers*/ + for (gpl= list->first; gpl; gpl= gpln) { + gpln= gpl->next; + + /* free layers and their data */ + free_gpencil_frames(gpl); + BLI_freelinkN(list, gpl); + } +} + +/* Free all of GPencil datablock's related data, but not the block itself */ +void free_gpencil_data (bGPdata *gpd) +{ + /* free layers */ + free_gpencil_layers(&gpd->layers); +} + +/* -------- Container Creation ---------- */ + +/* add a new gp-frame to the given layer */ +bGPDframe *gpencil_frame_addnew (bGPDlayer *gpl, int cframe) +{ + bGPDframe *gpf, *gf; + short state=0; + + /* error checking */ + if ((gpl == NULL) || (cframe <= 0)) + return NULL; + + /* allocate memory for this frame */ + gpf= MEM_callocN(sizeof(bGPDframe), "bGPDframe"); + gpf->framenum= cframe; + + /* find appropriate place to add frame */ + if (gpl->frames.first) { + for (gf= gpl->frames.first; gf; gf= gf->next) { + /* check if frame matches one that is supposed to be added */ + if (gf->framenum == cframe) { + state= -1; + break; + } + + /* if current frame has already exceeded the frame to add, add before */ + if (gf->framenum > cframe) { + BLI_insertlinkbefore(&gpl->frames, gf, gpf); + state= 1; + break; + } + } + } + + /* check whether frame was added successfully */ + if (state == -1) { + MEM_freeN(gpf); + printf("Error: frame (%d) existed already for this layer \n", cframe); + } + else if (state == 0) { + /* add to end then! */ + BLI_addtail(&gpl->frames, gpf); + } + + /* return frame */ + return gpf; +} + +/* add a new gp-layer and make it the active layer */ +bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) +{ + bGPDlayer *gpl; + + /* check that list is ok */ + if (gpd == NULL) + return NULL; + + /* allocate memory for frame and add to end of list */ + gpl= MEM_callocN(sizeof(bGPDlayer), "bGPDlayer"); + + /* add to datablock */ + BLI_addtail(&gpd->layers, gpl); + + /* set basic settings */ + gpl->color[3]= 0.9f; + gpl->thickness = 3; + + /* auto-name */ + sprintf(gpl->info, "GP_Layer"); + BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128); + + /* make this one the active one */ + gpencil_layer_setactive(gpd, gpl); + + /* return layer */ + return gpl; +} + +/* add a new gp-datablock */ +bGPdata *gpencil_data_addnew (char name[]) +{ + bGPdata *gpd; + + /* allocate memory for a new block */ + gpd= alloc_libblock(&G.main->gpencil, ID_GD, name); + + /* initial settings */ + gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); + + return gpd; +} + +/* -------- Data Duplication ---------- */ + +/* make a copy of a given gpencil frame */ +bGPDframe *gpencil_frame_duplicate (bGPDframe *src) +{ + bGPDstroke *gps, *gpsd; + bGPDframe *dst; + + /* error checking */ + if (src == NULL) + return NULL; + + /* make a copy of the source frame */ + dst= MEM_dupallocN(src); + dst->prev= dst->next= NULL; + + /* copy strokes */ + dst->strokes.first = dst->strokes.last= NULL; + for (gps= src->strokes.first; gps; gps= gps->next) { + /* make copy of source stroke, then adjust pointer to points too */ + gpsd= MEM_dupallocN(gps); + gpsd->points= MEM_dupallocN(gps->points); + + BLI_addtail(&dst->strokes, gpsd); + } + + /* return new frame */ + return dst; +} + +/* make a copy of a given gpencil layer */ +bGPDlayer *gpencil_layer_duplicate (bGPDlayer *src) +{ + bGPDframe *gpf, *gpfd; + bGPDlayer *dst; + + /* error checking */ + if (src == NULL) + return NULL; + + /* make a copy of source layer */ + dst= MEM_dupallocN(src); + dst->prev= dst->next= NULL; + + /* copy frames */ + dst->frames.first= dst->frames.last= NULL; + for (gpf= src->frames.first; gpf; gpf= gpf->next) { + /* make a copy of source frame */ + gpfd= gpencil_frame_duplicate(gpf); + BLI_addtail(&dst->frames, gpfd); + + /* if source frame was the current layer's 'active' frame, reassign that too */ + if (gpf == dst->actframe) + dst->actframe= gpfd; + } + + /* return new layer */ + return dst; +} + +/* make a copy of a given gpencil datablock */ +bGPdata *gpencil_data_duplicate (bGPdata *src) +{ + bGPDlayer *gpl, *gpld; + bGPdata *dst; + + /* error checking */ + if (src == NULL) + return NULL; + + /* make a copy of the base-data */ + dst= MEM_dupallocN(src); + + /* copy layers */ + dst->layers.first= dst->layers.last= NULL; + for (gpl= src->layers.first; gpl; gpl= gpl->next) { + /* make a copy of source layer and its data */ + gpld= gpencil_layer_duplicate(gpl); + BLI_addtail(&dst->layers, gpld); + } + + /* return new */ + return dst; +} + +/* -------- GP-Frame API ---------- */ + +/* delete the last stroke of the given frame */ +void gpencil_frame_delete_laststroke (bGPDlayer *gpl, bGPDframe *gpf) +{ + bGPDstroke *gps= (gpf) ? gpf->strokes.last : NULL; + int cfra = 1; // XXX FIXME!!! + + /* error checking */ + if (ELEM(NULL, gpf, gps)) + return; + + /* free the stroke and its data */ + MEM_freeN(gps->points); + BLI_freelinkN(&gpf->strokes, gps); + + /* if frame has no strokes after this, delete it */ + if (gpf->strokes.first == NULL) { + gpencil_layer_delframe(gpl, gpf); + gpencil_layer_getframe(gpl, cfra, 0); + } +} + +/* -------- GP-Layer API ---------- */ + +/* get the appropriate gp-frame from a given layer + * - this sets the layer's actframe var (if allowed to) + * - extension beyond range (if first gp-frame is after all frame in interest and cannot add) + */ +bGPDframe *gpencil_layer_getframe (bGPDlayer *gpl, int cframe, short addnew) +{ + bGPDframe *gpf = NULL; + short found = 0; + + /* error checking */ + if (gpl == NULL) return NULL; + if (cframe <= 0) cframe = 1; + + /* check if there is already an active frame */ + if (gpl->actframe) { + gpf= gpl->actframe; + + /* do not allow any changes to layer's active frame if layer is locked */ + if (gpl->flag & GP_LAYER_LOCKED) + return gpf; + /* do not allow any changes to actframe if frame has painting tag attached to it */ + if (gpf->flag & GP_FRAME_PAINT) + return gpf; + + /* try to find matching frame */ + if (gpf->framenum < cframe) { + for (; gpf; gpf= gpf->next) { + if (gpf->framenum == cframe) { + found= 1; + break; + } + else if ((gpf->next) && (gpf->next->framenum > cframe)) { + found= 1; + break; + } + } + + /* set the appropriate frame */ + if (addnew) { + if ((found) && (gpf->framenum == cframe)) + gpl->actframe= gpf; + else + gpl->actframe= gpencil_frame_addnew(gpl, cframe); + } + else if (found) + gpl->actframe= gpf; + else + gpl->actframe= gpl->frames.last; + } + else { + for (; gpf; gpf= gpf->prev) { + if (gpf->framenum <= cframe) { + found= 1; + break; + } + } + + /* set the appropriate frame */ + if (addnew) { + if ((found) && (gpf->framenum == cframe)) + gpl->actframe= gpf; + else + gpl->actframe= gpencil_frame_addnew(gpl, cframe); + } + else if (found) + gpl->actframe= gpf; + else + gpl->actframe= gpl->frames.first; + } + } + else if (gpl->frames.first) { + /* check which of the ends to start checking from */ + const int first= ((bGPDframe *)(gpl->frames.first))->framenum; + const int last= ((bGPDframe *)(gpl->frames.last))->framenum; + + if (abs(cframe-first) > abs(cframe-last)) { + /* find gp-frame which is less than or equal to cframe */ + for (gpf= gpl->frames.last; gpf; gpf= gpf->prev) { + if (gpf->framenum <= cframe) { + found= 1; + break; + } + } + } + else { + /* find gp-frame which is less than or equal to cframe */ + for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { + if (gpf->framenum <= cframe) { + found= 1; + break; + } + } + } + + /* set the appropriate frame */ + if (addnew) { + if ((found) && (gpf->framenum == cframe)) + gpl->actframe= gpf; + else + gpl->actframe= gpencil_frame_addnew(gpl, cframe); + } + else if (found) + gpl->actframe= gpf; + else { + /* unresolved errogenous situation! */ + printf("Error: cannot find appropriate gp-frame \n"); + /* gpl->actframe should still be NULL */ + } + } + else { + /* currently no frames (add if allowed to) */ + if (addnew) + gpl->actframe= gpencil_frame_addnew(gpl, cframe); + else { + /* don't do anything... this may be when no frames yet! */ + /* gpl->actframe should still be NULL */ + } + } + + /* return */ + return gpl->actframe; +} + +/* delete the given frame from a layer */ +void gpencil_layer_delframe (bGPDlayer *gpl, bGPDframe *gpf) +{ + /* error checking */ + if (ELEM(NULL, gpl, gpf)) + return; + + /* free the frame and its data */ + free_gpencil_strokes(gpf); + BLI_freelinkN(&gpl->frames, gpf); + gpl->actframe = NULL; +} + +/* get the active gp-layer for editing */ +bGPDlayer *gpencil_layer_getactive (bGPdata *gpd) +{ + bGPDlayer *gpl; + + /* error checking */ + if (ELEM(NULL, gpd, gpd->layers.first)) + return NULL; + + /* loop over layers until found (assume only one active) */ + for (gpl=gpd->layers.first; gpl; gpl=gpl->next) { + if (gpl->flag & GP_LAYER_ACTIVE) + return gpl; + } + + /* no active layer found */ + return NULL; +} + +/* set the active gp-layer */ +void gpencil_layer_setactive (bGPdata *gpd, bGPDlayer *active) +{ + bGPDlayer *gpl; + + /* error checking */ + if (ELEM3(NULL, gpd, gpd->layers.first, active)) + return; + + /* loop over layers deactivating all */ + for (gpl=gpd->layers.first; gpl; gpl=gpl->next) + gpl->flag &= ~GP_LAYER_ACTIVE; + + /* set as active one */ + active->flag |= GP_LAYER_ACTIVE; +} + +/* delete the active gp-layer */ +void gpencil_layer_delactive (bGPdata *gpd) +{ + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + + /* error checking */ + if (ELEM(NULL, gpd, gpl)) + return; + + /* free layer */ + free_gpencil_frames(gpl); + BLI_freelinkN(&gpd->layers, gpl); +} + +/* ************************************************** */ diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 0d2f86bb151..6fffbd794ef 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -280,7 +280,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode) you can draw everything, leaves tags in objects to signal it needs further updating */ /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */ -void group_handle_recalc_and_update(Object *parent, Group *group) +void group_handle_recalc_and_update(Scene *scene, Object *parent, Group *group) { GroupObject *go; @@ -289,8 +289,8 @@ void group_handle_recalc_and_update(Object *parent, Group *group) int cfrao; /* switch to local time */ - cfrao= G.scene->r.cfra; - G.scene->r.cfra -= (int)give_timeoffset(parent); + cfrao= scene->r.cfra; + scene->r.cfra -= (int)give_timeoffset(parent); /* we need a DAG per group... */ for(go= group->gobject.first; go; go= go->next) { @@ -298,7 +298,7 @@ void group_handle_recalc_and_update(Object *parent, Group *group) go->ob->recalc= go->recalc; group_replaces_nla(parent, go->ob, 's'); - object_handle_update(go->ob); + object_handle_update(scene, go->ob); group_replaces_nla(parent, go->ob, 'e'); /* leave recalc tags in case group members are in normal scene */ @@ -307,14 +307,14 @@ void group_handle_recalc_and_update(Object *parent, Group *group) } /* restore */ - G.scene->r.cfra= cfrao; + scene->r.cfra= cfrao; } else { /* only do existing tags, as set by regular depsgraph */ for(go= group->gobject.first; go; go= go->next) { if(go->ob) { if(go->ob->recalc) { - object_handle_update(go->ob); + object_handle_update(scene, go->ob); } } } diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 79ecbf09f55..3be47778674 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -25,6 +25,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + #include "DNA_listBase.h" #include "DNA_ID.h" @@ -37,10 +41,6 @@ #include "MEM_guardedalloc.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #define BSTR_EQ(a, b) (*(a) == *(b) && !strcmp(a, b)) /* IDPropertyTemplate is a union in DNA_ID.h */ @@ -58,8 +58,153 @@ static char idp_size_table[] = { sizeof(double) }; +/* ------------Property Array Type ----------- */ +#define GETPROP(prop, i) (((IDProperty*)(prop)->data.pointer)+(i)) + +/* --------- property array type -------------*/ + +/*note: as a start to move away from the stupid IDP_New function, this type + has it's own allocation function.*/ +IDProperty *IDP_NewIDPArray(const char *name) +{ + IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty prop array"); + prop->type = IDP_IDPARRAY; + prop->len = 0; + BLI_strncpy(prop->name, name, MAX_IDPROP_NAME); + + return prop; +} + +IDProperty *IDP_CopyIDPArray(IDProperty *array) +{ + IDProperty *narray = MEM_dupallocN(array), *tmp; + int i; + + narray->data.pointer = MEM_dupallocN(array->data.pointer); + for (i=0; i<narray->len; i++) { + /*ok, the copy functions always allocate a new structure, + which doesn't work here. instead, simply copy the + contents of the new structure into the array cell, + then free it. this makes for more maintainable + code than simply reimplementing the copy functions + in this loop.*/ + tmp = IDP_CopyProperty(GETPROP(narray, i)); + memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty)); + MEM_freeN(tmp); + } + + return narray; +} + +void IDP_FreeIDPArray(IDProperty *prop) +{ + int i; + + for (i=0; i<prop->len; i++) + IDP_FreeProperty(GETPROP(prop, i)); + + if(prop->data.pointer) + MEM_freeN(prop->data.pointer); +} + +/*shallow copies item*/ +void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) +{ + IDProperty *old = GETPROP(prop, index); + if (index >= prop->len || index < 0) return; + if (item != old) IDP_FreeProperty(old); + + memcpy(GETPROP(prop, index), item, sizeof(IDProperty)); +} + +IDProperty *IDP_GetIndexArray(IDProperty *prop, int index) +{ + return GETPROP(prop, index); +} + +IDProperty *IDP_AppendArray(IDProperty *prop, IDProperty *item) +{ + IDP_ResizeIDPArray(prop, prop->len+1); + IDP_SetIndexArray(prop, prop->len-1, item); + return item; +} + +void IDP_ResizeIDPArray(IDProperty *prop, int newlen) +{ + void *newarr; + int newsize=newlen; + + /*first check if the array buffer size has room*/ + /*if newlen is 200 chars less then totallen, reallocate anyway*/ + if (newlen <= prop->totallen && prop->totallen - newlen < 200) { + int i; + + for(i=newlen; i<prop->len; i++) + IDP_FreeProperty(GETPROP(prop, i)); + + prop->len = newlen; + return; + } + + /* - Note: This code comes from python, here's the corrusponding comment. - */ + /* This over-allocates proportional to the list size, making room + * for additional growth. The over-allocation is mild, but is + * enough to give linear-time amortized behavior over a long + * sequence of appends() in the presence of a poorly-performing + * system realloc(). + * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... + */ + newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; + + newarr = MEM_callocN(sizeof(IDProperty)*newsize, "idproperty array resized"); + if (newlen >= prop->len) { + /* newlen is bigger*/ + memcpy(newarr, prop->data.pointer, prop->len*sizeof(IDProperty)); + } + else { + int i; + /* newlen is smaller*/ + for (i=newlen; i<prop->len; i++) { + IDP_FreeProperty(GETPROP(prop, i)); + } + memcpy(newarr, prop->data.pointer, newlen*prop->len*sizeof(IDProperty)); + } -/* ----------- Array Type ----------- */ + if(prop->data.pointer) + MEM_freeN(prop->data.pointer); + prop->data.pointer = newarr; + prop->len = newlen; + prop->totallen = newsize; +} + +/* ----------- Numerical Array Type ----------- */ +static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) +{ + if(prop->subtype != IDP_GROUP) + return; + + if(newlen >= prop->len) { + /* bigger */ + IDProperty **array= newarr; + IDPropertyTemplate val; + int a; + + for(a=prop->len; a<newlen; a++) { + val.i = 0; /* silence MSVC warning about uninitialized var when debugging */ + array[a]= IDP_New(IDP_GROUP, val, "IDP_ResizeArray group"); + } + } + else { + /* smaller */ + IDProperty **array= prop->data.pointer; + int a; + + for(a=newlen; a<prop->len; a++) { + IDP_FreeProperty(array[a]); + MEM_freeN(array[a]); + } + } +} /*this function works for strings too!*/ void IDP_ResizeArray(IDProperty *prop, int newlen) @@ -70,6 +215,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) /*first check if the array buffer size has room*/ /*if newlen is 200 chars less then totallen, reallocate anyway*/ if (newlen <= prop->totallen && prop->totallen - newlen < 200) { + idp_resize_group_array(prop, newlen, prop->data.pointer); prop->len = newlen; return; } @@ -84,11 +230,17 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) */ newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; - newarr = MEM_callocN(idp_size_table[prop->type]*newsize, "idproperty array resized"); - /*newlen is bigger*/ - if (newlen >= prop->len) memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[prop->type]); - /*newlen is smaller*/ - else memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[prop->type]); + newarr = MEM_callocN(idp_size_table[prop->subtype]*newsize, "idproperty array resized"); + if (newlen >= prop->len) { + /* newlen is bigger*/ + memcpy(newarr, prop->data.pointer, prop->len*idp_size_table[prop->subtype]); + idp_resize_group_array(prop, newlen, newarr); + } + else { + /* newlen is smaller*/ + idp_resize_group_array(prop, newlen, newarr); + memcpy(newarr, prop->data.pointer, newlen*prop->len*idp_size_table[prop->subtype]); + } MEM_freeN(prop->data.pointer); prop->data.pointer = newarr; @@ -96,10 +248,12 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) prop->totallen = newsize; } - void IDP_FreeArray(IDProperty *prop) +void IDP_FreeArray(IDProperty *prop) { - if (prop->data.pointer) + if (prop->data.pointer) { + idp_resize_group_array(prop, 0, NULL); MEM_freeN(prop->data.pointer); + } } @@ -107,7 +261,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) { IDProperty *newp = MEM_callocN(sizeof(IDProperty), "IDProperty array dup"); - strncpy(newp->name, prop->name, MAX_IDPROP_NAME); + BLI_strncpy(newp->name, prop->name, MAX_IDPROP_NAME); newp->type = prop->type; newp->flag = prop->flag; newp->data.val = prop->data.val; @@ -120,7 +274,17 @@ IDProperty *IDP_CopyArray(IDProperty *prop) { IDProperty *newp = idp_generic_copy(prop); - if (prop->data.pointer) newp->data.pointer = MEM_dupallocN(prop->data.pointer); + if (prop->data.pointer) { + newp->data.pointer = MEM_dupallocN(prop->data.pointer); + + if(prop->type == IDP_GROUP) { + IDProperty **array= newp->data.pointer; + int a; + + for(a=0; a<prop->len; a++) + array[a]= IDP_CopyProperty(array[a]); + } + } newp->len = prop->len; newp->subtype = prop->subtype; newp->totallen = prop->totallen; @@ -187,7 +351,8 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append) void IDP_FreeString(IDProperty *prop) { - MEM_freeN(prop->data.pointer); + if(prop->data.pointer) + MEM_freeN(prop->data.pointer); } @@ -341,6 +506,7 @@ IDProperty *IDP_CopyProperty(IDProperty *prop) case IDP_GROUP: return IDP_CopyGroup(prop); case IDP_STRING: return IDP_CopyString(prop); case IDP_ARRAY: return IDP_CopyArray(prop); + case IDP_IDPARRAY: return IDP_CopyIDPArray(prop); default: return idp_generic_copy(prop); } } @@ -361,7 +527,61 @@ IDProperty *IDP_GetProperties(ID *id, int create_if_needed) } } -IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name) +int IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) +{ + if(prop1 == NULL && prop2 == NULL) + return 1; + else if(prop1 == NULL || prop2 == NULL) + return 0; + else if(prop1->type != prop2->type) + return 0; + + if(prop1->type == IDP_INT) + return (IDP_Int(prop1) == IDP_Int(prop2)); + else if(prop1->type == IDP_FLOAT) + return (IDP_Float(prop1) == IDP_Float(prop2)); + else if(prop1->type == IDP_DOUBLE) + return (IDP_Double(prop1) == IDP_Double(prop2)); + else if(prop1->type == IDP_STRING) + return BSTR_EQ(IDP_String(prop1), IDP_String(prop2)); + else if(prop1->type == IDP_ARRAY) { + if(prop1->len == prop2->len && prop1->subtype == prop2->subtype) + return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[prop1->subtype]*prop1->len); + else + return 0; + } + else if(prop1->type == IDP_GROUP) { + IDProperty *link1, *link2; + + if(BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + return 0; + + for(link1=prop1->data.group.first; link1; link1=link1->next) { + link2= IDP_GetPropertyFromGroup(prop2, link1->name); + + if(!IDP_EqualsProperties(link1, link2)) + return 0; + } + + return 1; + } + else if(prop1->type == IDP_IDPARRAY) { + IDProperty *array1= IDP_IDPArray(prop1); + IDProperty *array2= IDP_IDPArray(prop2); + int i; + + if(prop1->len != prop2->len) + return 0; + + for(i=0; i<prop1->len; i++) + if(!IDP_EqualsProperties(&array1[i], &array2[i])) + return 0; + } + + return 1; +} + +IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name) { IDProperty *prop=NULL; @@ -381,11 +601,12 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name) case IDP_ARRAY: { /*for now, we only support float and int and double arrays*/ - if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT || val.array.type == IDP_DOUBLE) { + if (val.array.type == IDP_FLOAT || val.array.type == IDP_INT || val.array.type == IDP_DOUBLE || val.array.type == IDP_GROUP) { prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); - prop->len = prop->totallen = val.array.len; prop->subtype = val.array.type; - prop->data.pointer = MEM_callocN(idp_size_table[val.array.type]*val.array.len, "id property array"); + if (val.array.len) + prop->data.pointer = MEM_callocN(idp_size_table[val.array.type]*val.array.len, "id property array"); + prop->len = prop->totallen = val.array.len; break; } else { return NULL; @@ -423,7 +644,7 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, char *name) } prop->type = type; - strncpy(prop->name, name, MAX_IDPROP_NAME); + BLI_strncpy(prop->name, name, MAX_IDPROP_NAME); /*security null byte*/ prop->name[MAX_IDPROP_NAME-1] = 0; @@ -446,6 +667,9 @@ void IDP_FreeProperty(IDProperty *prop) case IDP_GROUP: IDP_FreeGroup(prop); break; + case IDP_IDPARRAY: + IDP_FreeIDPArray(prop); + break; } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index e817c38618f..8eef9984c92 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -21,9 +21,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. - * - * Contributor(s): Blender Foundation, 2006 + * Contributor(s): Blender Foundation, 2006, full recode * * ***** END GPL LICENSE BLOCK ***** */ @@ -55,6 +53,7 @@ #include "DNA_camera_types.h" #include "DNA_sequence_types.h" #include "DNA_texture_types.h" +#include "DNA_sequence_types.h" #include "DNA_userdef_types.h" #include "BLI_arithb.h" @@ -72,18 +71,12 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" -#include "BIF_editseq.h" +//XXX #include "BIF_editseq.h" #include "PIL_time.h" #include "RE_pipeline.h" -/* for stamp drawing to an image */ -#include "BMF_Api.h" - -#include "blendef.h" -#include "BSE_time.h" - #include "GPU_extensions.h" #include "GPU_draw.h" @@ -95,6 +88,7 @@ /* quick lookup: supports 1 million frames, thousand passes */ #define IMA_MAKE_INDEX(frame, index) ((frame)<<10)+index #define IMA_INDEX_FRAME(index) (index>>10) +#define IMA_INDEX_PASS(index) (index & ~1023) /* ******** IMAGE PROCESSING ************* */ @@ -336,10 +330,42 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) } } +/* empty image block, of similar type and filename */ +Image *BKE_image_copy(Image *ima) +{ + Image *new= image_alloc(ima->id.name+2, ima->source, ima->type); + + BLI_strncpy(new->name, ima->name, sizeof(ima->name)); + + new->gen_x= ima->gen_x; + new->gen_y= ima->gen_y; + new->gen_type= ima->gen_type; + + return new; +} + +void BKE_image_merge(Image *dest, Image *source) +{ + ImBuf *ibuf; + + /* sanity check */ + if(dest && source && dest!=source) { + + while((ibuf= source->ibufs.first)) { + BLI_remlink(&source->ibufs, ibuf); + image_assign_ibuf(dest, ibuf, IMA_INDEX_PASS(ibuf->index), IMA_INDEX_FRAME(ibuf->index)); + } + + free_libblock(&G.main->image, source); + } +} + + /* checks if image was already loaded, then returns same image */ /* otherwise creates new. */ /* does not load ibuf itself */ -Image *BKE_add_image_file(const char *name) +/* pass on optional frame for #name images */ +Image *BKE_add_image_file(const char *name, int frame) { Image *ima; int file, len; @@ -355,7 +381,7 @@ Image *BKE_add_image_file(const char *name) BLI_strncpy(str, name, sizeof(str)); BLI_convertstringcode(str, G.sce); - BLI_convertstringframe(str, G.scene->r.cfra); /* TODO - should this realy be here? */ + BLI_convertstringframe(str, frame); /* exists? */ file= open(str, O_BINARY|O_RDONLY); @@ -367,7 +393,7 @@ Image *BKE_add_image_file(const char *name) if(ima->source!=IMA_SRC_VIEWER && ima->source!=IMA_SRC_GENERATED) { BLI_strncpy(strtest, ima->name, sizeof(ima->name)); BLI_convertstringcode(strtest, G.sce); - BLI_convertstringframe(strtest, G.scene->r.cfra); /* TODO - should this be here? */ + BLI_convertstringframe(strtest, frame); if( strcmp(strtest, str)==0 ) { if(ima->anim==NULL || ima->id.us==0) { @@ -407,7 +433,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho unsigned char *rect= NULL; float *rect_float= NULL; int x, y; - int checkerwidth=21, dark=1; + int checkerwidth=32, dark=1; if (floatbuf) { ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0); @@ -418,7 +444,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, sho rect= (unsigned char*)ibuf->rect; } - strcpy(ibuf->name, "Untitled"); + strcpy(ibuf->name, "//Untitled"); ibuf->userflags |= IB_BITMAPDIRTY; if (uvtestgrid) { @@ -585,6 +611,7 @@ void tag_image_time(Image *ima) ima->lastused = (int)PIL_check_seconds_timer(); } +#if 0 static void tag_all_images_time() { Image *ima; @@ -597,6 +624,7 @@ static void tag_all_images_time() } } } +#endif void free_old_images() { @@ -640,6 +668,11 @@ static uintptr_t image_mem_size(Image *ima) uintptr_t size = 0; size= 0; + + /* viewers have memory depending on other rules, has no valid rect pointer */ + if(ima->source==IMA_SRC_VIEWER) + return 0; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { if(ibuf->rect) size += MEM_allocN_len(ibuf->rect); else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float); @@ -829,11 +862,11 @@ int BKE_imtype_is_movie(int imtype) return 0; } -void BKE_add_image_extension(char *string, int imtype) +void BKE_add_image_extension(Scene *scene, char *string, int imtype) { char *extension=""; - if(G.scene->r.imtype== R_IRIS) { + if(scene->r.imtype== R_IRIS) { if(!BLI_testextensie(string, ".rgb")) extension= ".rgb"; } @@ -912,7 +945,7 @@ typedef struct StampData { char strip[64]; } StampData; -static void stampdata(StampData *stamp_data, int do_prefix) +static void stampdata(Scene *scene, StampData *stamp_data, int do_prefix) { char text[256]; @@ -923,7 +956,7 @@ static void stampdata(StampData *stamp_data, int do_prefix) char sdate[9]; #endif /* WIN32 */ - if (G.scene->r.stamp & R_STAMP_FILENAME) { + if (scene->r.stamp & R_STAMP_FILENAME) { if (G.relbase_valid) { if (do_prefix) sprintf(stamp_data->file, "File %s", G.sce); else sprintf(stamp_data->file, "%s", G.sce); @@ -936,14 +969,14 @@ static void stampdata(StampData *stamp_data, int do_prefix) stamp_data->file[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_NOTE) { + if (scene->r.stamp & R_STAMP_NOTE) { /* Never do prefix for Note */ - sprintf(stamp_data->note, "%s", G.scene->r.stamp_udata); + sprintf(stamp_data->note, "%s", scene->r.stamp_udata); } else { stamp_data->note[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_DATE) { + if (scene->r.stamp & R_STAMP_DATE) { #ifdef WIN32 _strdate (sdate); sprintf (text, "%s", sdate); @@ -958,8 +991,8 @@ static void stampdata(StampData *stamp_data, int do_prefix) stamp_data->date[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_MARKER) { - TimeMarker *marker = get_frame_marker(CFRA); + if (scene->r.stamp & R_STAMP_MARKER) { + TimeMarker *marker = NULL; // XXX get_frame_marker(scene->r.cfra); if (marker) strcpy(text, marker->name); else strcpy(text, "<none>"); @@ -970,11 +1003,11 @@ static void stampdata(StampData *stamp_data, int do_prefix) stamp_data->marker[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_TIME) { + if (scene->r.stamp & R_STAMP_TIME) { int h, m, s, f; h= m= s= f= 0; - f = (int)(G.scene->r.cfra % G.scene->r.frs_sec); - s = (int)(G.scene->r.cfra / G.scene->r.frs_sec); + f = (int)(scene->r.cfra % scene->r.frs_sec); + s = (int)(scene->r.cfra / scene->r.frs_sec); if (s) { m = (int)(s / 60); @@ -986,7 +1019,7 @@ static void stampdata(StampData *stamp_data, int do_prefix) } } - if (G.scene->r.frs_sec < 100) + if (scene->r.frs_sec < 100) sprintf (text, "%02d:%02d:%02d.%02d", h, m, s, f); else sprintf (text, "%02d:%02d:%02d.%03d", h, m, s, f); @@ -997,17 +1030,17 @@ static void stampdata(StampData *stamp_data, int do_prefix) stamp_data->time[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_FRAME) { + if (scene->r.stamp & R_STAMP_FRAME) { char format[32]; - if (do_prefix) sprintf(format, "Frame %%0%di\n", 1 + (int) log10(G.scene->r.efra)); - else sprintf(format, "%%0%di\n", 1 + (int) log10(G.scene->r.efra)); - sprintf (stamp_data->frame, format, G.scene->r.cfra); + if (do_prefix) sprintf(format, "Frame %%0%di\n", 1 + (int) log10(scene->r.efra)); + else sprintf(format, "%%0%di\n", 1 + (int) log10(scene->r.efra)); + sprintf (stamp_data->frame, format, scene->r.cfra); } else { stamp_data->frame[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_CAMERA) { - if (G.scene->camera) strcpy(text, ((Camera *) G.scene->camera)->id.name+2); + if (scene->r.stamp & R_STAMP_CAMERA) { + if (scene->camera) strcpy(text, ((Camera *) scene->camera)->id.name+2); else strcpy(text, "<none>"); if (do_prefix) sprintf(stamp_data->camera, "Camera %s", text); @@ -1016,15 +1049,15 @@ static void stampdata(StampData *stamp_data, int do_prefix) stamp_data->camera[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_SCENE) { - if (do_prefix) sprintf(stamp_data->scene, "Scene %s", G.scene->id.name+2); - else sprintf(stamp_data->scene, "%s", G.scene->id.name+2); + if (scene->r.stamp & R_STAMP_SCENE) { + if (do_prefix) sprintf(stamp_data->scene, "Scene %s", scene->id.name+2); + else sprintf(stamp_data->scene, "%s", scene->id.name+2); } else { stamp_data->scene[0] = '\0'; } - if (G.scene->r.stamp & R_STAMP_SEQSTRIP) { - Sequence *seq = get_forground_frame_seq(CFRA); + if (scene->r.stamp & R_STAMP_SEQSTRIP) { + Sequence *seq= NULL; //XXX = get_foreground_frame_seq(scene->r.cfra); if (seq) strcpy(text, seq->name+2); else strcpy(text, "<none>"); @@ -1036,8 +1069,11 @@ static void stampdata(StampData *stamp_data, int do_prefix) } } -void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int channels) +void BKE_stamp_buf(Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels) { +#if 0 +// XXX +// This go back when BLF_draw_buffer is implemented - Diego struct StampData stamp_data; int x=1,y=1; @@ -1049,9 +1085,9 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int if (!rect && !rectf) return; - stampdata(&stamp_data, 1); + stampdata(scene, &stamp_data, 1); - switch (G.scene->r.stamp_font_id) { + switch (scene->r.stamp_font_id) { case 1: /* tiny */ font = BMF_GetFont(BMF_kHelveticaBold8); break; @@ -1083,24 +1119,24 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int if (stamp_data.file[0]) { /* Top left corner */ text_width = BMF_GetStringWidth(font, stamp_data.file); - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } /* Top left corner, below File */ if (stamp_data.note[0]) { text_width = BMF_GetStringWidth(font, stamp_data.note); - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } /* Top left corner, below File (or Note) */ if (stamp_data.date[0]) { text_width = BMF_GetStringWidth(font, stamp_data.date); - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Bottom left corner, leaving space for timing */ @@ -1108,8 +1144,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int x = 1; y = font_height+2+1; /* 2 for padding in TIME|FRAME fields below and 1 for padding in this one */ text_width = BMF_GetStringWidth(font, stamp_data.marker); - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Left bottom corner */ @@ -1117,8 +1153,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int x = 1; y = 1; text_width = BMF_GetStringWidth(font, stamp_data.time); - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); x += text_width+text_pad+2; /* Both sides have 1 pix additional padding each */ } @@ -1127,8 +1163,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int /* Left bottom corner (after SMPTE if exists) */ if (!stamp_data.time[0]) x = 1; y = 1; - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.camera[0]) { @@ -1136,8 +1172,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int /* Center of bottom edge */ x = (width/2) - (BMF_GetStringWidth(font, stamp_data.camera)/2); y = 1; - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.scene[0]) { @@ -1145,8 +1181,8 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int /* Bottom right corner */ x = width - (text_width+1+text_pad); y = 1; - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.strip[0]) { @@ -1154,20 +1190,20 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int /* Top right corner */ x = width - (text_width+1+text_pad); y = height - font_height - 1; - buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); + buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); + BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, scene->r.fg_stamp, rect, rectf, width, height, channels); } - +#endif // 0 XXX } -void BKE_stamp_info(struct ImBuf *ibuf) +void BKE_stamp_info(Scene *scene, struct ImBuf *ibuf) { struct StampData stamp_data; if (!ibuf) return; /* fill all the data values, no prefix */ - stampdata(&stamp_data, 0); + stampdata(scene, &stamp_data, 0); if (stamp_data.file[0]) IMB_imginfo_change_field (ibuf, "File", stamp_data.file); if (stamp_data.note[0]) IMB_imginfo_change_field (ibuf, "Note", stamp_data.note); @@ -1180,7 +1216,7 @@ void BKE_stamp_info(struct ImBuf *ibuf) if (stamp_data.strip[0]) IMB_imginfo_change_field (ibuf, "Strip", stamp_data.strip); } -int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quality) +int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimtype, int quality) { int ok; @@ -1265,8 +1301,8 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali BLI_make_existing_file(name); - if(G.scene->r.scemode & R_STAMP_INFO) - BKE_stamp_info(ibuf); + if(scene->r.scemode & R_STAMP_INFO) + BKE_stamp_info(scene, ibuf); ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); if (ok == 0) { @@ -1277,7 +1313,7 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali } -void BKE_makepicstring(char *string, char *base, int frame, int imtype) +void BKE_makepicstring(struct Scene *scene, char *string, char *base, int frame, int imtype) { if (string==NULL) return; @@ -1290,8 +1326,8 @@ void BKE_makepicstring(char *string, char *base, int frame, int imtype) BLI_convertstringcode(string, G.sce); BLI_convertstringframe(string, frame); - if(G.scene->r.scemode & R_EXTENSION) - BKE_add_image_extension(string, imtype); + if(scene->r.scemode & R_EXTENSION) + BKE_add_image_extension(scene, string, imtype); } @@ -1462,12 +1498,12 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) return rpass; } -RenderResult *BKE_image_get_renderresult(Image *ima) +RenderResult *BKE_image_get_renderresult(struct Scene *scene, Image *ima) { if(ima->rr) return ima->rr; if(ima->type==IMA_TYPE_R_RESULT) - return RE_GetResult(RE_GetRender(G.scene->id.name)); + return RE_GetResult(RE_GetRender(scene->id.name)); return NULL; } @@ -1770,11 +1806,30 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) /* showing RGBA result itself (from compo/sequence) or like exr, using layers etc */ +/* always returns a single ibuf, also during render progress */ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) { - RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); + Render *re= NULL; + RenderResult *rr= NULL; + + if(iuser->scene) { + re= RE_GetRender(iuser->scene->id.name); + rr= RE_GetResult(re); + } + if(rr==NULL) return NULL; - if(rr) { + if(RE_RenderInProgress(re)) { + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + + /* make ibuf if needed, and initialize it */ + /* this only gets called when mutex locked */ + if(ibuf==NULL) { + ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, IB_rect, 0); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } + return ibuf; + } + else { RenderResult rres; float *rectf; unsigned int *rect; @@ -1786,10 +1841,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ - RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + RE_GetResultImage(RE_GetRender(iuser->scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; - dither= G.scene->r.dither_intensity; + dither= iuser->scene->r.dither_intensity; /* get compo/seq result by default */ if(rr->rectf && layer==0); @@ -1964,7 +2019,7 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) else if(ima->source==IMA_SRC_FILE) { if(ima->type==IMA_TYPE_IMAGE) - ibuf= image_load_image_file(ima, iuser, G.scene->r.cfra); /* cfra only for '#', this global is OK */ + ibuf= image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ /* no else; on load the ima type can change */ if(ima->type==IMA_TYPE_MULTILAYER) /* keeps render result, stores ibufs in listbase, allows saving */ @@ -1973,17 +2028,12 @@ ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) } else if(ima->source == IMA_SRC_GENERATED) { /* generated is: ibuf is allocated dynamically */ - if(ima->type==IMA_TYPE_VERSE) { - /* todo */ - } - else { /* always fall back to IMA_TYPE_UV_TEST */ - /* UV testgrid or black or solid etc */ - if(ima->gen_x==0) ima->gen_x= 256; - if(ima->gen_y==0) ima->gen_y= 256; - ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 0, ima->gen_type, color); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok= IMA_OK_LOADED; - } + /* UV testgrid or black or solid etc */ + if(ima->gen_x==0) ima->gen_x= 256; + if(ima->gen_y==0) ima->gen_y= 256; + ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 0, ima->gen_type, color); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok= IMA_OK_LOADED; } else if(ima->source == IMA_SRC_VIEWER) { if(ima->type==IMA_TYPE_R_RESULT) { diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 93e35a4db06..40c98c1d9cc 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1393,7 +1393,7 @@ float calculateVertexWindForce(float wind[3], float vertexnormal[3]) return (INPR(wind, vertexnormal)); } -void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) +static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) { /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; @@ -1442,7 +1442,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec { float speed[3] = {0.0f, 0.0f,0.0f}; - pdDoEffectors(effectors, lX[i], winvec[i], speed, (float)G.scene->r.cfra, 0.0f, 0); + pdDoEffectors(clmd->scene, effectors, lX[i], winvec[i], speed, frame, 0.0f, 0); } for(i = 0; i < cloth->numfaces; i++) @@ -1570,8 +1570,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase while(step < tf) { // calculate forces - effectors= pdInitEffectors(ob,NULL); - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M); + effectors= pdInitEffectors(clmd->scene, ob, NULL); + cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M); if(effectors) pdEndEffectors(effectors); // calculate new velocity @@ -1648,8 +1648,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cp_lfvector(id->V, id->Vnew, numverts); // calculate - effectors= pdInitEffectors(ob,NULL); - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M); + effectors= pdInitEffectors(clmd->scene, ob, NULL); + cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step+dt, id->M); if(effectors) pdEndEffectors(effectors); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI); diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 29db0ddd808..8cbf25eaeed 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -23,14 +23,23 @@ * * The Original Code is: all of this file. * - * Contributor(s): 2008, Joshua Leung (IPO System cleanup) + * Contributor(s): 2008,2009 Joshua Leung (IPO System cleanup, Animation System Recode) * * ***** END GPL LICENSE BLOCK ***** */ +/* NOTE: + * + * This file is no longer used to provide tools for the depreceated IPO system. Instead, it + * is only used to house the conversion code to the new system. + * + * -- Joshua Leung, Jan 2009 + */ + #include <math.h> #include <stdio.h> #include <string.h> +#include <stddef.h> #ifdef HAVE_CONFIG_H #include <config.h> @@ -38,8 +47,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" +#include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_camera_types.h" #include "DNA_lamp_types.h" @@ -59,14 +70,16 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_dynstr.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_blender.h" #include "BKE_curve.h" #include "BKE_constraint.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_library.h" @@ -74,2811 +87,1658 @@ #include "BKE_mesh.h" #include "BKE_object.h" -#ifndef DISABLE_PYTHON -#include "BPY_extern.h" /* for BPY_pydriver_eval() */ -#endif - -#define SMALL -1.0e-10 - -/* ***************************** Adrcode Blocktype Defines ********************************* */ - -/* This array concept was meant to make sure that defines such as OB_LOC_X - don't have to be enumerated, also for backward compatibility, future changes, - and to enable it all can be accessed with a for-next loop. - - This should whole adrcode system should eventually be replaced by a proper Data API -*/ - - -int co_ar[CO_TOTIPO]= { - CO_ENFORCE, CO_HEADTAIL -}; - -int ob_ar[OB_TOTIPO]= { - OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z, - OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z, - OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z, - OB_LAY, OB_TIME, OB_COL_R, OB_COL_G, OB_COL_B, OB_COL_A, - OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM, OB_PD_FMAXD -}; - -int ac_ar[AC_TOTIPO]= { - AC_LOC_X, AC_LOC_Y, AC_LOC_Z, - AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z, - AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z -}; - -int ma_ar[MA_TOTIPO]= { - MA_COL_R, MA_COL_G, MA_COL_B, - MA_SPEC_R, MA_SPEC_G, MA_SPEC_B, - MA_MIR_R, MA_MIR_G, MA_MIR_B, - MA_REF, MA_ALPHA, MA_EMIT, MA_AMB, - MA_SPEC, MA_HARD, MA_SPTR, MA_IOR, - MA_MODE, MA_HASIZE, MA_TRANSLU, MA_RAYM, - MA_FRESMIR, MA_FRESMIRI, MA_FRESTRA, MA_FRESTRAI, MA_ADD, - - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF, MA_MAP1+MAP_DISP -}; - -int te_ar[TE_TOTIPO] ={ - - TE_NSIZE, TE_NDEPTH, TE_NTYPE, TE_TURB, - - TE_VNW1, TE_VNW2, TE_VNW3, TE_VNW4, - TE_VNMEXP, TE_VN_COLT, TE_VN_DISTM, - - TE_ISCA, TE_DISTA, - - TE_MG_TYP, TE_MGH, TE_MG_LAC, TE_MG_OCT, TE_MG_OFF, TE_MG_GAIN, - - TE_N_BAS1, TE_N_BAS2, - - TE_COL_R, TE_COL_G, TE_COL_B, TE_BRIGHT, TE_CONTRA -}; - -int seq_ar[SEQ_TOTIPO]= { - SEQ_FAC1 -}; -int cu_ar[CU_TOTIPO]= { - CU_SPEED -}; -int wo_ar[WO_TOTIPO]= { - WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B, - WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI, - WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE, +/* *************************************************** */ +/* Old-Data Freeing Tools */ - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF -}; - -int la_ar[LA_TOTIPO]= { - LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B, - LA_DIST, LA_SPOTSI, LA_SPOTBL, - LA_QUAD1, LA_QUAD2, LA_HALOINT, - - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF -}; - -/* yafray: aperture & focal distance curves added */ -/* qdn: FDIST now available to Blender as well for defocus node */ -int cam_ar[CAM_TOTIPO]= { - CAM_LENS, CAM_STA, CAM_END, CAM_YF_APERT, CAM_YF_FDIST, CAM_SHIFT_X, CAM_SHIFT_Y -}; - -int snd_ar[SND_TOTIPO]= { - SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN -}; - -int fluidsim_ar[FLUIDSIM_TOTIPO]= { - FLUIDSIM_VISC, FLUIDSIM_TIME, - FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z , - FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z , - FLUIDSIM_ACTIVE, - FLUIDSIM_ATTR_FORCE_STR, FLUIDSIM_ATTR_FORCE_RADIUS, - FLUIDSIM_VEL_FORCE_STR, FLUIDSIM_VEL_FORCE_RADIUS, -}; - -int part_ar[PART_TOTIPO]= { - PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE, - PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP, - PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE, - PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD -}; - -/* ************************** Data-Level Functions ************************* */ - -/* ---------------------- Freeing --------------------------- */ - -/* frees the ipo curve itself too */ -void free_ipo_curve (IpoCurve *icu) -{ - if (icu == NULL) - return; - - if (icu->bezt) - MEM_freeN(icu->bezt); - if (icu->driver) - MEM_freeN(icu->driver); - - MEM_freeN(icu); -} - -/* do not free ipo itself */ +/* Free data from old IPO-Blocks (those which haven't been converted), but not IPO block itself */ +// XXX this shouldn't be necessary anymore, but may occur while not all data is converted yet void free_ipo (Ipo *ipo) { IpoCurve *icu, *icn; - - if (ipo == NULL) - return; + int n= 0; for (icu= ipo->curve.first; icu; icu= icn) { icn= icu->next; + n++; + + if (icu->bezt) MEM_freeN(icu->bezt); + if (icu->bp) MEM_freeN(icu->bp); + if (icu->driver) MEM_freeN(icu->driver); - /* must remove the link before freeing, as the curve is freed too */ - BLI_remlink(&ipo->curve, icu); - free_ipo_curve(icu); + BLI_freelinkN(&ipo->curve, icu); } + + if (G.f & G_DEBUG) + printf("Freed %d (Unconverted) Ipo-Curves from IPO '%s' \n", n, ipo->id.name+2); } -/* ---------------------- Init --------------------------- */ +/* *************************************************** */ +/* ADRCODE to RNA-Path Conversion Code - Special (Bitflags) */ + +/* Mapping Table for bitflag <-> RNA path */ +typedef struct AdrBit2Path { + int bit; + char *path; + int array_index; +} AdrBit2Path; + +/* ----------------- */ +/* Mapping Tables to use bits <-> RNA paths */ + +/* Object layers */ +static AdrBit2Path ob_layer_bits[]= { + {(1<<0), "layer", 0}, + {(1<<1), "layer", 1}, + {(1<<2), "layer", 2}, + {(1<<3), "layer", 3}, + {(1<<4), "layer", 4}, + {(1<<5), "layer", 5}, + {(1<<6), "layer", 6}, + {(1<<7), "layer", 7}, + {(1<<8), "layer", 8}, + {(1<<9), "layer", 9}, + {(1<<10), "layer", 10}, + {(1<<11), "layer", 11}, + {(1<<12), "layer", 12}, + {(1<<13), "layer", 13}, + {(1<<14), "layer", 14}, + {(1<<15), "layer", 15}, + {(1<<16), "layer", 16}, + {(1<<17), "layer", 17}, + {(1<<18), "layer", 18}, + {(1<<19), "layer", 19}, + {(1<<20), "layer", 20} +}; -/* on adding new ipos, or for empty views */ -void ipo_default_v2d_cur (int blocktype, rctf *cur) -{ - switch (blocktype) { - case ID_CA: - cur->xmin= (float)G.scene->r.sfra; - cur->xmax= (float)G.scene->r.efra; - cur->ymin= 0.0f; - cur->ymax= 100.0f; - break; - - case ID_MA: case ID_WO: case ID_LA: - case ID_CU: case ID_CO: - cur->xmin= (float)(G.scene->r.sfra - 0.1f); - cur->xmax= (float)G.scene->r.efra; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+1.1f; - break; - - case ID_TE: - cur->xmin= (float)(G.scene->r.sfra - 0.1f); - cur->xmax= (float)G.scene->r.efra; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+1.1f; - break; - - case ID_SEQ: - cur->xmin= -5.0f; - cur->xmax= 105.0f; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+1.1f; - break; - - case ID_KE: - cur->xmin= (float)(G.scene->r.sfra - 0.1f); - cur->xmax= (float)G.scene->r.efra; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+2.1f; - break; - - default: /* ID_OB and everything else */ - cur->xmin= (float)G.scene->r.sfra; - cur->xmax= (float)G.scene->r.efra; - cur->ymin= -5.0f; - cur->ymax= +5.0f; - break; +/* Material mode */ +static AdrBit2Path ma_mode_bits[]= { +// {MA_TRACEBLE, "traceable", 0}, +// {MA_SHADOW, "shadow", 0}, +// {MA_SHLESS, "shadeless", 0}, +// ... + {MA_RAYTRANSP, "raytrace_transparency.enabled", 0}, + {MA_RAYMIRROR, "raytrace_mirror.enabled", 0}, +// {MA_HALO, "type", MA_TYPE_HALO} +}; + +/* ----------------- */ + +/* quick macro for returning the appropriate array for adrcode_bitmaps_to_paths() */ +#define RET_ABP(items) \ + { \ + *tot= sizeof(items)/sizeof(AdrBit2Path); \ + return items; \ } -} -/* create a new IPO block (allocates the block) */ -Ipo *add_ipo (char name[], int blocktype) +/* This function checks if a Blocktype+Adrcode combo, returning a mapping table */ +static AdrBit2Path *adrcode_bitmaps_to_paths (int blocktype, int adrcode, int *tot) { - Ipo *ipo; - - ipo= alloc_libblock(&G.main->ipo, ID_IP, name); - ipo->blocktype= blocktype; - ipo_default_v2d_cur(blocktype, &ipo->cur); - - return ipo; + /* Object layers */ + if ((blocktype == ID_OB) && (adrcode == OB_LAY)) + RET_ABP(ob_layer_bits) + else if ((blocktype == ID_MA) && (adrcode == MA_MODE)) + RET_ABP(ma_mode_bits) + // XXX TODO: add other types... + + /* Normal curve */ + return NULL; } -/* ---------------------- Copy --------------------------- */ +/* *************************************************** */ +/* ADRCODE to RNA-Path Conversion Code - Standard */ -/* duplicate an IPO block and all its data */ -Ipo *copy_ipo (Ipo *src) +/* Object types */ +static char *ob_adrcodes_to_paths (int adrcode, int *array_index) { - Ipo *dst; - IpoCurve *icu; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - if (src == NULL) - return NULL; - - dst= copy_libblock(src); - duplicatelist(&dst->curve, &src->curve); - - for (icu= src->curve.first; icu; icu= icu->next) { - icu->bezt= MEM_dupallocN(icu->bezt); + /* result depends on adrcode */ + switch (adrcode) { + case OB_LOC_X: + *array_index= 0; return "location"; + case OB_LOC_Y: + *array_index= 1; return "location"; + case OB_LOC_Z: + *array_index= 2; return "location"; + case OB_DLOC_X: + *array_index= 0; return "delta_location"; + case OB_DLOC_Y: + *array_index= 1; return "delta_location"; + case OB_DLOC_Z: + *array_index= 2; return "delta_location"; - if (icu->driver) - icu->driver= MEM_dupallocN(icu->driver); + case OB_ROT_X: + *array_index= 0; return "rotation"; + case OB_ROT_Y: + *array_index= 1; return "rotation"; + case OB_ROT_Z: + *array_index= 2; return "rotation"; + case OB_DROT_X: + *array_index= 0; return "delta_rotation"; + case OB_DROT_Y: + *array_index= 1; return "delta_rotation"; + case OB_DROT_Z: + *array_index= 2; return "delta_rotation"; + + case OB_SIZE_X: + *array_index= 0; return "scale"; + case OB_SIZE_Y: + *array_index= 1; return "scale"; + case OB_SIZE_Z: + *array_index= 2; return "scale"; + case OB_DSIZE_X: + *array_index= 0; return "delta_scale"; + case OB_DSIZE_Y: + *array_index= 1; return "delta_scale"; + case OB_DSIZE_Z: + *array_index= 2; return "delta_scale"; + +#if 0 + case OB_COL_R: + poin= &(ob->col[0]); break; + case OB_COL_G: + poin= &(ob->col[1]); break; + case OB_COL_B: + poin= &(ob->col[2]); break; + case OB_COL_A: + poin= &(ob->col[3]); break; + + case OB_PD_FSTR: + if (ob->pd) poin= &(ob->pd->f_strength); + break; + case OB_PD_FFALL: + if (ob->pd) poin= &(ob->pd->f_power); + break; + case OB_PD_SDAMP: + if (ob->pd) poin= &(ob->pd->pdef_damp); + break; + case OB_PD_RDAMP: + if (ob->pd) poin= &(ob->pd->pdef_rdamp); + break; + case OB_PD_PERM: + if (ob->pd) poin= &(ob->pd->pdef_perm); + break; + case OB_PD_FMAXD: + if (ob->pd) poin= &(ob->pd->maxdist); + break; +#endif } - return dst; + return NULL; } -/* ---------------------- Relink --------------------------- */ - -/* uses id->newid to match pointers with other copied data - * - called after single-user or other such +/* PoseChannel types + * NOTE: pchan name comes from 'actname' added earlier... */ -void ipo_idnew (Ipo *ipo) -{ - if (ipo) { - IpoCurve *icu; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->driver) - ID_NEW(icu->driver->ob); - } - } -} - -/* --------------------- Find + Check ----------------------- */ - -/* find the IPO-curve within a given IPO-block with the adrcode of interest */ -IpoCurve *find_ipocurve (Ipo *ipo, int adrcode) +static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) { - if (ipo) { - IpoCurve *icu; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; + + /* result depends on adrcode */ + switch (adrcode) { + case AC_QUAT_W: + *array_index= 0; return "rotation"; + case AC_QUAT_X: + *array_index= 1; return "rotation"; + case AC_QUAT_Y: + *array_index= 2; return "rotation"; + case AC_QUAT_Z: + *array_index= 3; return "rotation"; + + case AC_EUL_X: + *array_index= 0; return "euler_rotation"; + case AC_EUL_Y: + *array_index= 1; return "euler_rotation"; + case AC_EUL_Z: + *array_index= 2; return "euler_rotation"; + + case -1: // XXX special case for rotation drivers... until eulers are added... + *array_index= 0; return "rotation"; + + case AC_LOC_X: + *array_index= 0; return "location"; + case AC_LOC_Y: + *array_index= 1; return "location"; + case AC_LOC_Z: + *array_index= 2; return "location"; - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->adrcode == adrcode) - return icu; - } + case AC_SIZE_X: + *array_index= 0; return "scale"; + case AC_SIZE_Y: + *array_index= 1; return "scale"; + case AC_SIZE_Z: + *array_index= 2; return "scale"; } + + /* for debugging only */ + printf("ERROR: unmatched PoseChannel setting (code %d) \n", adrcode); return NULL; } -/* return whether the given IPO block has a IPO-curve with the given adrcode */ -short has_ipo_code(Ipo *ipo, int adrcode) +/* Constraint types */ +static char *constraint_adrcodes_to_paths (int adrcode, int *array_index) { - /* return success of faliure from trying to find such an IPO-curve */ - return (find_ipocurve(ipo, adrcode) != NULL); -} - -/* ---------------------- Make Local --------------------------- */ - - -/* make the given IPO local (for Objects) - * - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ -void make_local_obipo (Ipo *src) -{ - Object *ob; - Ipo *dst; - int local=0, lib=0; - - /* check if only local and/or lib */ - for (ob= G.main->object.first; ob; ob= ob->id.next) { - if (ob->ipo == src) { - if (ob->id.lib) lib= 1; - else local= 1; - } - } + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; - - for (ob= G.main->object.first; ob; ob= ob->id.next) { - if (ob->ipo == src) { - if (ob->id.lib == NULL) { - ob->ipo= dst; - dst->id.us++; - src->id.us--; - } - } - } + /* result depends on adrcode */ + switch (adrcode) { + case CO_ENFORCE: + return "influence"; + case CO_HEADTAIL: // XXX this needs to be wrapped in RNA.. probably then this path will be invalid + return "data.head_tail"; } + + return NULL; } -/* make the given IPO local (for Materials) - * - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy +/* ShapeKey types + * NOTE: as we don't have access to the keyblock where the data comes from (for now), + * we'll just use numerical indicies for now... */ -void make_local_matipo (Ipo *src) +static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index) { - Material *ma; - Ipo *dst; - int local=0, lib=0; - - /* check if only local and/or lib */ - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == src) { - if (ma->id.lib) lib= 1; - else local= 1; - } - } + static char buf[128]; - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; - - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == src) { - if (ma->id.lib == NULL) { - ma->ipo= dst; - dst->id.us++; - src->id.us--; - } - } - } - } + /* block will be attached to ID_KE block, and setting that we alter is the 'value' (which sets keyblock.curval) */ + // XXX adrcode 0 was dummy 'speed' curve + if (adrcode == 0) + sprintf(buf, "speed"); + else + sprintf(buf, "keys[%d].value", adrcode); + return buf; } -/* make the given IPO local (for ShapeKeys) - * - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ -void make_local_keyipo (Ipo *src) +/* MTex (Texture Slot) types */ +static char *mtex_adrcodes_to_paths (int adrcode, int *array_index) { - Key *key; - Ipo *dst; - int local=0, lib=0; - - /* check if only local and/or lib */ - for (key= G.main->key.first; key; key= key->id.next) { - if (key->ipo == src) { - if (key->id.lib) lib= 1; - else local= 1; - } + char *base=NULL, *prop=NULL; + static char buf[128]; + + /* base part of path */ + if (adrcode & MA_MAP1) base= "textures[0]"; + else if (adrcode & MA_MAP2) base= "textures[1]"; + else if (adrcode & MA_MAP3) base= "textures[2]"; + else if (adrcode & MA_MAP4) base= "textures[3]"; + else if (adrcode & MA_MAP5) base= "textures[4]"; + else if (adrcode & MA_MAP6) base= "textures[5]"; + else if (adrcode & MA_MAP7) base= "textures[6]"; + else if (adrcode & MA_MAP8) base= "textures[7]"; + else if (adrcode & MA_MAP9) base= "textures[8]"; + else if (adrcode & MA_MAP10) base= "textures[9]"; + else if (adrcode & MA_MAP11) base= "textures[10]"; + else if (adrcode & MA_MAP12) base= "textures[11]"; + else if (adrcode & MA_MAP13) base= "textures[12]"; + else if (adrcode & MA_MAP14) base= "textures[13]"; + else if (adrcode & MA_MAP15) base= "textures[14]"; + else if (adrcode & MA_MAP16) base= "textures[15]"; + else if (adrcode & MA_MAP17) base= "textures[16]"; + else if (adrcode & MA_MAP18) base= "textures[17]"; + + /* property identifier for path */ + adrcode= (adrcode & (MA_MAP1-1)); + switch (adrcode) { +#if 0 // XXX these are not wrapped in RNA yet! + case MAP_OFS_X: + poin= &(mtex->ofs[0]); break; + case MAP_OFS_Y: + poin= &(mtex->ofs[1]); break; + case MAP_OFS_Z: + poin= &(mtex->ofs[2]); break; + case MAP_SIZE_X: + poin= &(mtex->size[0]); break; + case MAP_SIZE_Y: + poin= &(mtex->size[1]); break; + case MAP_SIZE_Z: + poin= &(mtex->size[2]); break; + case MAP_R: + poin= &(mtex->r); break; + case MAP_G: + poin= &(mtex->g); break; + case MAP_B: + poin= &(mtex->b); break; + case MAP_DVAR: + poin= &(mtex->def_var); break; + case MAP_COLF: + poin= &(mtex->colfac); break; + case MAP_NORF: + poin= &(mtex->norfac); break; + case MAP_VARF: + poin= &(mtex->varfac); break; +#endif + case MAP_DISP: + prop= "warp_factor"; break; } - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; - - for (key= G.main->key.first; key; key= key->id.next) { - if (key->ipo == src) { - if (key->id.lib == NULL) { - key->ipo= dst; - dst->id.us++; - src->id.us--; - } - } - } + /* only build and return path if there's a property */ + if (prop) { + BLI_snprintf(buf, 128, "%s.%s", base, prop); + return buf; } + else + return NULL; } - -/* generic call to make IPO's local */ -void make_local_ipo (Ipo *ipo) +/* Texture types */ +static char *texture_adrcodes_to_paths (int adrcode, int *array_index) { - /* can't touch lib-linked data */ - if (ipo->id.lib == NULL) - return; - - /* with only one user, just set local flag */ - if (ipo->id.us == 1) { - ipo->id.lib= 0; - ipo->id.flag= LIB_LOCAL; - new_id(0, (ID *)ipo, 0); - return; - } + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* when more than 1 user, can only make local for certain blocktypes */ - switch (ipo->blocktype) { - case ID_OB: - make_local_obipo(ipo); + /* result depends on adrcode */ + switch (adrcode) { + case TE_NSIZE: + return "noise_size"; + case TE_TURB: + return "turbulence"; + + case TE_NDEPTH: // XXX texture RNA undefined + //poin= &(tex->noisedepth); *type= IPO_SHORT; break; break; - case ID_MA: - make_local_matipo(ipo); + case TE_NTYPE: // XXX texture RNA undefined + //poin= &(tex->noisetype); *type= IPO_SHORT; break; break; - case ID_KE: - make_local_keyipo(ipo); + + case TE_N_BAS1: + return "noise_basis"; + case TE_N_BAS2: + return "noise_basis"; // XXX this is not yet defined in RNA... + + /* voronoi */ + case TE_VNW1: + *array_index= 0; return "feature_weights"; + case TE_VNW2: + *array_index= 1; return "feature_weights"; + case TE_VNW3: + *array_index= 2; return "feature_weights"; + case TE_VNW4: + *array_index= 3; return "feature_weights"; + case TE_VNMEXP: + return "minkovsky_exponent"; + case TE_VN_DISTM: + return "distance_metric"; + case TE_VN_COLT: + return "color_type"; + + /* distorted noise / voronoi */ + case TE_ISCA: + return "noise_intensity"; + + /* distorted noise */ + case TE_DISTA: + return "distortion_amount"; + + /* musgrave */ + case TE_MG_TYP: // XXX texture RNA undefined + // poin= &(tex->stype); *type= IPO_SHORT; break; break; + case TE_MGH: + return "highest_dimension"; + case TE_MG_LAC: + return "lacunarity"; + case TE_MG_OCT: + return "octaves"; + case TE_MG_OFF: + return "offset"; + case TE_MG_GAIN: + return "gain"; + + case TE_COL_R: + *array_index= 0; return "rgb_factor"; + case TE_COL_G: + *array_index= 1; return "rgb_factor"; + case TE_COL_B: + *array_index= 2; return "rgb_factor"; + + case TE_BRIGHT: + return "brightness"; + case TE_CONTRA: + return "constrast"; } + + return NULL; } -/* ***************************** Keyframe Column Tools ********************************* */ - -/* add a BezTriple to a column */ -void add_to_cfra_elem(ListBase *lb, BezTriple *bezt) +/* Material Types */ +static char *material_adrcodes_to_paths (int adrcode, int *array_index) { - CfraElem *ce, *cen; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - for (ce= lb->first; ce; ce= ce->next) { - /* double key? */ - if (ce->cfra == bezt->vec[1][0]) { - if (bezt->f2 & SELECT) ce->sel= bezt->f2; - return; - } - /* should key be inserted before this column? */ - else if (ce->cfra > bezt->vec[1][0]) break; + /* result depends on adrcode */ + switch (adrcode) { + case MA_COL_R: + *array_index= 0; return "diffuse_color"; + case MA_COL_G: + *array_index= 1; return "diffuse_color"; + case MA_COL_B: + *array_index= 2; return "diffuse_color"; + + case MA_SPEC_R: + *array_index= 0; return "specular_color"; + case MA_SPEC_G: + *array_index= 1; return "specular_color"; + case MA_SPEC_B: + *array_index= 2; return "specular_color"; + + case MA_MIR_R: + *array_index= 0; return "mirror_color"; + case MA_MIR_G: + *array_index= 1; return "mirror_color"; + case MA_MIR_B: + *array_index= 2; return "mirror_color"; + + case MA_ALPHA: + return "alpha"; + + case MA_REF: + return "diffuse_reflection"; + + case MA_EMIT: + return "emit"; + + case MA_AMB: + return "ambient"; + + case MA_SPEC: + return "specularity"; + + case MA_HARD: + return "specular_hardness"; + + case MA_SPTR: + return "specular_opacity"; + + case MA_IOR: + return "ior"; + + case MA_HASIZE: + return "halo.size"; + + case MA_TRANSLU: + return "translucency"; + + case MA_RAYM: + return "raytrace_mirror.reflect"; + + case MA_FRESMIR: + return "raytrace_mirror.fresnel"; + + case MA_FRESMIRI: + return "raytrace_mirror.fresnel_fac"; + + case MA_FRESTRA: + return "raytrace_transparency.fresnel"; + + case MA_FRESTRAI: + return "raytrace_transparency.fresnel_fac"; + + case MA_ADD: + return "halo.add"; + + default: /* for now, we assume that the others were MTex channels */ + return mtex_adrcodes_to_paths(adrcode, array_index); } - /* create a new column */ - cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); - if (ce) BLI_insertlinkbefore(lb, ce, cen); - else BLI_addtail(lb, cen); - - cen->cfra= bezt->vec[1][0]; - cen->sel= bezt->f2; + return NULL; } -/* make a list of keyframe 'columns' in an IPO block */ -void make_cfra_list (Ipo *ipo, ListBase *elems) +/* Camera Types */ +static char *camera_adrcodes_to_paths (int adrcode, int *array_index) { - IpoCurve *icu; - BezTriple *bezt; - int a; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->flag & IPO_VISIBLE) { - /* ... removed old checks for adrcode types from here ... - * - (was this used for IpoKeys in the past?) - */ + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; + + /* result depends on adrcode */ + switch (adrcode) { + case CAM_LENS: +#if 0 // XXX this cannot be resolved easily... perhaps we assume camera is perspective (works for most cases... + if (ca->type == CAM_ORTHO) + return "ortho_scale"; + else + return "lens"; +#endif // XXX this cannot be resolved easily + break; - bezt= icu->bezt; - if (bezt) { - for (a=0; a < icu->totvert; a++, bezt++) { - add_to_cfra_elem(elems, bezt); - } - } - } + case CAM_STA: + return "clip_start"; + case CAM_END: + return "clip_end"; + +#if 0 // XXX these are not defined in RNA + case CAM_YF_APERT: + poin= &(ca->YF_aperture); break; + case CAM_YF_FDIST: + poin= &(ca->YF_dofdist); break; +#endif // XXX these are not defined in RNA + + case CAM_SHIFT_X: + return "shift_x"; + case CAM_SHIFT_Y: + return "shift_y"; } -} - -/* ***************************** Timing Stuff ********************************* */ - -/* This (evil) function is needed to cope with two legacy Blender rendering features - * mblur (motion blur that renders 'subframes' and blurs them together), and fields - * rendering. Thus, the use of ugly globals from object.c - */ -// BAD... EVIL... JUJU...!!!! -float frame_to_float (int cfra) /* see also bsystem_time in object.c */ -{ - extern float bluroffs; /* bad stuff borrowed from object.c */ - extern float fieldoffs; - float ctime; - ctime= (float)cfra; - ctime+= bluroffs+fieldoffs; - ctime*= G.scene->r.framelen; - - return ctime; + /* unrecognised adrcode, or not-yet-handled ones! */ + return NULL; } -/* ***************************** IPO Curve Sanity ********************************* */ -/* The functions here are used in various parts of Blender, usually after some editing - * of keyframe data has occurred. They ensure that keyframe data is properly ordered and - * that the handles are correctly - */ - -/* This function recalculates the handles of an IPO-Curve - * If the BezTriples have been rearranged, sort them first before using this. - */ -void calchandles_ipocurve (IpoCurve *icu) +/* Lamp Types */ +static char *lamp_adrcodes_to_paths (int adrcode, int *array_index) { - BezTriple *bezt, *prev, *next; - int a= icu->totvert; - - /* Error checking: - * - need at least two points - * - need bezier keys - * - only bezier-interpolation has handles (for now) - */ - if (ELEM(NULL, icu, icu->bezt) || (a < 2) || ELEM(icu->ipo, IPO_CONST, IPO_LIN)) - return; - - /* get initial pointers */ - bezt= icu->bezt; - prev= NULL; - next= (bezt + 1); + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* loop over all beztriples, adjusting handles */ - while (a--) { - /* clamp timing of handles to be on either side of beztriple */ - if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0]; - if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0]; - - /* calculate autohandles */ - if (icu->flag & IPO_AUTO_HORIZ) - calchandleNurb(bezt, prev, next, 2); /* 2==special autohandle && keep extrema horizontal */ - else - calchandleNurb(bezt, prev, next, 1); /* 1==special autohandle */ - - /* for automatic ease in and out */ - if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) { - /* only do this on first or last beztriple */ - if ((a==0) || (a==icu->totvert-1)) { - /* set both handles to have same horizontal value as keyframe */ - if (icu->extrap==IPO_HORIZ) { - bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; - } - } - } + /* result depends on adrcode */ + switch (adrcode) { + case LA_ENERGY: + return "energy"; + + case LA_COL_R: + *array_index= 0; return "color"; + case LA_COL_G: + *array_index= 1; return "color"; + case LA_COL_B: + *array_index= 2; return "color"; + + case LA_DIST: + return "distance"; - /* advance pointers for next iteration */ - prev= bezt; - if (a == 1) next= NULL; - else next++; - bezt++; + case LA_SPOTSI: + return "spot_size"; + case LA_SPOTBL: + return "spot_blend"; + + case LA_QUAD1: + return "linear_attenuation"; + case LA_QUAD2: + return "quadratic_attenuation"; + + case LA_HALOINT: + return "halo_intensity"; + + default: /* for now, we assume that the others were MTex channels */ + return mtex_adrcodes_to_paths(adrcode, array_index); } + + /* unrecognised adrcode, or not-yet-handled ones! */ + return NULL; } -/* Use when IPO-Curve with handles has changed - * It treats all BezTriples with the following rules: - * - PHASE 1: do types have to be altered? - * -> Auto handles: become aligned when selection status is NOT(000 || 111) - * -> Vector handles: become 'nothing' when (one half selected AND other not) - * - PHASE 2: recalculate handles -*/ -void testhandles_ipocurve (IpoCurve *icu) +/* Sound Types */ +static char *sound_adrcodes_to_paths (int adrcode, int *array_index) { - BezTriple *bezt; - int a; - - /* only beztriples have handles (bpoints don't though) */ - if (ELEM(NULL, icu, icu->bezt)) - return; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* loop over beztriples */ - for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) { - short flag= 0; - - /* flag is initialised as selection status - * of beztriple control-points (labelled 0,1,2) - */ - if (bezt->f1 & SELECT) flag |= (1<<0); // == 1 - if (bezt->f2 & SELECT) flag |= (1<<1); // == 2 - if (bezt->f3 & SELECT) flag |= (1<<2); // == 4 - - /* one or two handles selected only */ - if (ELEM(flag, 0, 7)==0) { - /* auto handles become aligned */ - if (bezt->h1==HD_AUTO) - bezt->h1= HD_ALIGN; - if(bezt->h2==HD_AUTO) - bezt->h2= HD_ALIGN; - - /* vector handles become 'free' when only one half selected */ - if(bezt->h1==HD_VECT) { - /* only left half (1 or 2 or 1+2) */ - if (flag < 4) - bezt->h1= 0; - } - if(bezt->h2==HD_VECT) { - /* only right half (4 or 2+4) */ - if (flag > 3) - bezt->h2= 0; - } - } + /* result depends on adrcode */ + switch (adrcode) { + case SND_VOLUME: + return "volume"; + case SND_PITCH: + return "pitch"; + /* XXX Joshua -- I had wrapped panning in rna, but someone commented out, calling it "unused" */ + /* case SND_PANNING: + return "panning"; */ + case SND_ATTEN: + return "attenuation"; } - - /* recalculate handles */ - calchandles_ipocurve(icu); + + /* unrecognised adrcode, or not-yet-handled ones! */ + return NULL; } -/* This function sorts BezTriples so that they are arranged in chronological order, - * as tools working on IPO-Curves expect that the BezTriples are in order. - */ -void sort_time_ipocurve(IpoCurve *icu) +/* World Types */ +static char *world_adrcodes_to_paths (int adrcode, int *array_index) { - short ok= 1; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* keep adjusting order of beztriples until nothing moves (bubble-sort) */ - while (ok) { - ok= 0; + /* result depends on adrcode */ + switch (adrcode) { + case WO_HOR_R: + *array_index= 0; return "horizon_color"; + case WO_HOR_G: + *array_index= 1; return "horizon_color"; + case WO_HOR_B: + *array_index= 2; return "horizon_color"; + case WO_ZEN_R: + *array_index= 0; return "zenith_color"; + case WO_ZEN_G: + *array_index= 1; return "zenith_color"; + case WO_ZEN_B: + *array_index= 2; return "zenith_color"; - /* currently, will only be needed when there are beztriples */ - if (icu->bezt) { - BezTriple *bezt; - int a; - - /* loop over ALL points to adjust position in array and recalculate handles */ - for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) { - /* check if thee's a next beztriple which we could try to swap with current */ - if (a < (icu->totvert-1)) { - /* swap if one is after the other (and indicate that order has changed) */ - if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) { - SWAP(BezTriple, *bezt, *(bezt+1)); - ok= 1; - } - - /* if either one of both of the points exceeds crosses over the keyframe time... */ - if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) { - /* swap handles if they have switched sides for some reason */ - SWAP(float, bezt->vec[0][0], bezt->vec[2][0]); - SWAP(float, bezt->vec[0][1], bezt->vec[2][1]); - } - else { - /* clamp handles */ - if (bezt->vec[0][0] > bezt->vec[1][0]) - bezt->vec[0][0]= bezt->vec[1][0]; - if (bezt->vec[2][0] < bezt->vec[1][0]) - bezt->vec[2][0]= bezt->vec[1][0]; - } - } - } + case WO_EXPOS: + return "exposure"; + + case WO_MISI: + return "mist.intensity"; + case WO_MISTDI: + return "mist.depth"; + case WO_MISTSTA: + return "mist.start"; + case WO_MISTHI: + return "mist.height"; + + /* Star Color is unused -- recommend removal */ + /* case WO_STAR_R: + *array_index= 0; return "stars.color"; + case WO_STAR_G: + *array_index= 1; return "stars.color"; + case WO_STAR_B: + *array_index= 2; return "stars.color"; */ + + case WO_STARDIST: + return "stars.min_distance"; + case WO_STARSIZE: + return "stars.size"; + + default: /* for now, we assume that the others were MTex channels */ + return mtex_adrcodes_to_paths(adrcode, array_index); } - } + + return NULL; } -/* This function tests if any BezTriples are out of order, thus requiring a sort */ -int test_time_ipocurve (IpoCurve *icu) +/* Particle Types */ +static char *particle_adrcodes_to_paths (int adrcode, int *array_index) { - int a; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* currently, only need to test beztriples */ - if (icu->bezt) { - BezTriple *bezt; + /* result depends on adrcode */ + switch (adrcode) { + case PART_CLUMP: + return "settings.clump_factor"; + case PART_AVE: + return "settings.angular_velocity_factor"; + case PART_SIZE: + return "settings.particle_size"; + case PART_DRAG: + return "settings.drag_factor"; + case PART_BROWN: + return "settings.brownian_factor"; + case PART_DAMP: + return "settings.damp_factor"; + case PART_LENGTH: + return "settings.length"; + case PART_GRAV_X: + *array_index= 0; return "settings.acceleration"; + case PART_GRAV_Y: + *array_index= 1; return "settings.acceleration"; + case PART_GRAV_Z: + *array_index= 2; return "settings.acceleration"; + case PART_KINK_AMP: + return "settings.kink_amplitude"; + case PART_KINK_FREQ: + return "settings.kink_frequency"; + case PART_KINK_SHAPE: + return "settings.kink_shape"; + case PART_BB_TILT: + return "settings.billboard_tilt"; - /* loop through all beztriples, stopping when one exceeds the one after it */ - for (a=0, bezt= icu->bezt; a < (icu->totvert - 1); a++, bezt++) { - if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) - return 1; + /* PartDeflect needs to be sorted out properly in rna_object_force; + If anyone else works on this, but is unfamiliar, these particular + settings reference the particles of the system themselves + being used as forces -- it will use the same rna structure + as the similar object forces */ + /*case PART_PD_FSTR: + if (part->pd) poin= &(part->pd->f_strength); + break; + case PART_PD_FFALL: + if (part->pd) poin= &(part->pd->f_power); + break; + case PART_PD_FMAXD: + if (part->pd) poin= &(part->pd->maxdist); + break; + case PART_PD2_FSTR: + if (part->pd2) poin= &(part->pd2->f_strength); + break; + case PART_PD2_FFALL: + if (part->pd2) poin= &(part->pd2->f_power); + break; + case PART_PD2_FMAXD: + if (part->pd2) poin= &(part->pd2->maxdist); + break;*/ + } - } - - /* none need any swapping */ - return 0; + + return NULL; } -/* --------- */ +/* ------- */ -/* The total length of the handles is not allowed to be more - * than the horizontal distance between (v1-v4). - * This is to prevent curve loops. -*/ -void correct_bezpart (float *v1, float *v2, float *v3, float *v4) +/* Allocate memory for RNA-path for some property given a blocktype, adrcode, and 'root' parts of path + * Input: + * - blocktype, adrcode - determines setting to get + * - actname, constname - used to build path + * Output: + * - array_index - index in property's array (if applicable) to use + * - return - the allocated path... + */ +char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) { - float h1[2], h2[2], len1, len2, len, fac; - - /* calculate handle deltas */ - h1[0]= v1[0]-v2[0]; - h1[1]= v1[1]-v2[1]; - h2[0]= v4[0]-v3[0]; - h2[1]= v4[1]-v3[1]; - - /* calculate distances: - * - len = span of time between keyframes - * - len1 = length of handle of start key - * - len2 = length of handle of end key - */ - len= v4[0]- v1[0]; - len1= (float)fabs(h1[0]); - len2= (float)fabs(h2[0]); + DynStr *path= BLI_dynstr_new(); + char *propname=NULL, *rpath=NULL; + char buf[512]; + int dummy_index= 0; - /* if the handles have no length, no need to do any corrections */ - if ((len1+len2) == 0.0) - return; + /* get property name based on blocktype */ + switch (blocktype) { + case ID_OB: /* object */ + propname= ob_adrcodes_to_paths(adrcode, &dummy_index); + break; - /* the two handles cross over each other, so force them - * apart using the proportion they overlap + case ID_PO: /* pose channel */ + propname= pchan_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_KE: /* shapekeys */ + propname= shapekey_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_CO: /* constraint */ + propname= constraint_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_TE: /* texture */ + propname= texture_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_MA: /* material */ + propname= material_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_CA: /* camera */ + propname= camera_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_LA: /* lamp */ + propname= lamp_adrcodes_to_paths(adrcode, &dummy_index); + break; + + case ID_SO: /* sound */ + propname= sound_adrcodes_to_paths(adrcode, &dummy_index); + + case ID_WO: /* world */ + propname= world_adrcodes_to_paths(adrcode, &dummy_index); + + case ID_PA: /* particle */ + propname= particle_adrcodes_to_paths(adrcode, &dummy_index); + + /* XXX problematic blocktypes */ + case ID_CU: /* curve */ + propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var... + break; + + case ID_SEQ: /* sequencer strip */ + //SEQ_FAC1: + // poin= &(seq->facf0); // XXX this doesn't seem to be included anywhere in sequencer RNA... + break; + + /* special hacks */ + case -1: + /* special case for rotdiff drivers... we don't need a property for this... */ + break; + + // TODO... add other blocktypes... + default: + printf("IPO2ANIMATO WARNING: No path for blocktype %d, adrcode %d yet \n", blocktype, adrcode); + break; + } + + /* check if any property found + * - blocktype < 0 is special case for a specific type of driver, where we don't need a property name... */ - if ((len1+len2) > len) { - fac= len/(len1+len2); + if ((propname == NULL) && (blocktype > 0)) { + /* nothing was found, so exit */ + if (array_index) + *array_index= 0; + + BLI_dynstr_free(path); - v2[0]= (v1[0]-fac*h1[0]); - v2[1]= (v1[1]-fac*h1[1]); + return NULL; + } + else { + if (array_index) + *array_index= dummy_index; + } + + /* append preceeding bits to path */ + if ((actname && actname[0]) && (constname && constname[0])) { + /* Constraint in Pose-Channel */ + sprintf(buf, "pose.pose_channels[\"%s\"].constraints[\"%s\"]", actname, constname); + } + else if (actname && actname[0]) { + /* Pose-Channel */ + sprintf(buf, "pose.pose_channels[\"%s\"]", actname); + } + else if (constname && constname[0]) { + /* Constraint in Object */ + sprintf(buf, "constraints[\"%s\"]", constname); + } + else + strcpy(buf, ""); /* empty string */ + BLI_dynstr_append(path, buf); + + /* append property to path (only if applicable) */ + if (blocktype > 0) { + /* need to add dot before property if there was anything precceding this */ + if (buf[0]) + BLI_dynstr_append(path, "."); - v3[0]= (v4[0]-fac*h2[0]); - v3[1]= (v4[1]-fac*h2[1]); + /* now write name of property */ + BLI_dynstr_append(path, propname); } -} - -#if 0 // TODO: enable when we have per-segment interpolation -/* This function sets the interpolation mode for an entire Ipo-Curve. - * It is primarily used for patching old files, but is also used in the interface - * to make sure that all segments of the curve use the same interpolation. - */ -void set_interpolation_ipocurve (IpoCurve *icu, short ipo) -{ - BezTriple *bezt; - int a; - /* validate arguments */ - if (icu == NULL) return; - if (ELEM3(ipo, IPO_CONST, IPO_LIN, IPO_BEZ)==0) return; - - /* set interpolation mode for whole curve */ - icu->ipo= ipo; + /* convert to normal MEM_malloc'd string */ + rpath= BLI_dynstr_get_cstring(path); + BLI_dynstr_free(path); - /* set interpolation mode of all beztriples */ - for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++) - bezt->ipo= ipo; + /* return path... */ + return rpath; } -#endif // TODO: enable when we have per-segment interpolation -/* ***************************** Curve Calculations ********************************* */ +/* *************************************************** */ +/* Conversion Utilities */ -/* find root/zero */ -int findzero (float x, float q0, float q1, float q2, float q3, float *o) +/* Convert IpoDriver to ChannelDriver - will free the old data (i.e. the old driver) */ +static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) { - double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; - int nr= 0; - - c0= q0 - x; - c1= 3 * (q1 - q0); - c2= 3 * (q0 - 2*q1 + q2); - c3= q3 - q0 + 3 * (q1 - q2); - - if (c3 != 0.0) { - a= c2/c3; - b= c1/c3; - c= c0/c3; - a= a/3; - - p= b/3 - a*a; - q= (2*a*a*a - a*b + c) / 2; - d= q*q + p*p*p; - - if (d > 0.0) { - t= sqrt(d); - o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; - } - else if (d == 0.0) { - t= Sqrt3d(-q); - o[0]= (float)(2*t - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)(-t-a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; - } - else { - phi= acos(-q / sqrt(-(p*p*p))); - t= sqrt(-p); - p= cos(phi/3); - q= sqrt(3 - 3*p*p); - o[0]= (float)(2*t*p - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)(-t * (p + q) - a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++; - o[nr]= (float)(-t * (p - q) - a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; - } + ChannelDriver *cdriver; + DriverTarget *dtar=NULL, *dtar2=NULL; + + /* allocate memory for new driver */ + cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + + /* if 'pydriver', just copy data across */ + if (idriver->type == IPO_DRIVER_TYPE_PYTHON) { + /* PyDriver only requires the expression to be copied */ + // TODO: but the expression will be useless... + cdriver->type = DRIVER_TYPE_PYTHON; + strcpy(cdriver->expression, idriver->name); // XXX is this safe? } else { - a=c2; - b=c1; - c=c0; - - if (a != 0.0) { - // discriminant - p= b*b - 4*a*c; - - if (p > 0) { - p= sqrt(p); - o[0]= (float)((-b-p) / (2 * a)); + /* what to store depends on the 'blocktype' (ID_OB or ID_PO - object or posechannel) */ + if (idriver->blocktype == ID_AR) { + /* ID_PO */ + if (idriver->adrcode == OB_ROT_DIFF) { + /* Rotational Difference is a special type of driver now... */ + cdriver->type= DRIVER_TYPE_ROTDIFF; + + /* make 2 driver targets */ + dtar= driver_add_new_target(cdriver); + dtar2= driver_add_new_target(cdriver); - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)((-b+p)/(2*a)); + /* driver must use bones from same armature... */ + dtar->id= dtar2->id= (ID *)idriver->ob; - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; + /* paths for the two targets get the pointers to the relevant Pose-Channels + * - return pointers to Pose-Channels not rotation channels, as calculation code is picky + * - old bone names were stored in same var, in idriver->name + * + * - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and + * providing a name for 'actname' will automatically imply Pose-Channel with name 'actname' + */ + dtar->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL); + dtar2->rna_path= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL); } - else if (p == 0) { - o[0]= (float)(-b / (2 * a)); - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; + else { + /* 'standard' driver */ + cdriver->type= DRIVER_TYPE_AVERAGE; + + /* make 1 driver target */ + dtar= driver_add_new_target(cdriver); + dtar->id= (ID *)idriver->ob; + + switch (idriver->adrcode) { + case OB_LOC_X: /* x,y,z location are quite straightforward */ + dtar->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &dtar->array_index); + break; + case OB_LOC_Y: + dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &dtar->array_index); + break; + case OB_LOC_Z: + dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &dtar->array_index); + break; + + case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */ + dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &dtar->array_index); + break; + case OB_SIZE_Y: + dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &dtar->array_index); + break; + case OB_SIZE_Z: + dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &dtar->array_index); + break; + + case OB_ROT_X: /* rotation - we need to be careful with this... XXX (another reason why we need eulers) */ + case OB_ROT_Y: + case OB_ROT_Z: + { + // XXX this is not yet a 1:1 map, since we'd need euler rotations to make this work nicely (unless we make some hacks) + // XXX -1 here is a special hack... + dtar->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL); + dtar->array_index= idriver->adrcode - OB_ROT_X; + } + break; + } } } - else if (b != 0.0) { - o[0]= (float)(-c/b); + else { + /* ID_OB */ + cdriver->type= DRIVER_TYPE_AVERAGE; - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; - } - else if (c == 0.0) { - o[0]= 0.0; - return 1; + /* make 1 driver target */ + dtar= driver_add_new_target(cdriver); + + dtar->id= (ID *)idriver->ob; + dtar->rna_path= get_rna_access(ID_OB, idriver->adrcode, NULL, NULL, &dtar->array_index); } - - return 0; - } -} - -void berekeny (float f1, float f2, float f3, float f4, float *o, int b) -{ - float t, c0, c1, c2, c3; - int a; - - c0= f1; - c1= 3.0f * (f2 - f1); - c2= 3.0f * (f1 - 2.0f*f2 + f3); - c3= f4 - f1 + 3.0f * (f2 - f3); - - for (a=0; a < b; a++) { - t= o[a]; - o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; - } -} - -void berekenx (float *f, float *o, int b) -{ - float t, c0, c1, c2, c3; - int a; - - c0= f[0]; - c1= 3 * (f[3] - f[0]); - c2= 3 * (f[0] - 2*f[3] + f[6]); - c3= f[9] - f[0] + 3 * (f[3] - f[6]); - - for (a=0; a < b; a++) { - t= o[a]; - o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; } + + + /* free old driver */ + MEM_freeN(idriver); + + /* return the new one */ + return cdriver; } -/* ***************************** IPO - Calculations ********************************* */ - -/* ---------------------- Curve Evaluation --------------------------- */ - -/* helper function for evaluating drivers: - * - we need the local transform = current transform - (parent transform + bone transform) - * - (local transform is on action channel level) +/* Add F-Curve to the correct list + * - grpname is needed to be used as group name where relevant, and is usually derived from actname */ -static void posechannel_get_local_transform (bPoseChannel *pchan, float loc[], float eul[], float size[]) +static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, char *grpname) { - float parmat[4][4], offs_bone[4][4], imat[4][4]; - float diff_mat[4][4]; - - /* get first the parent + bone transform in parmat */ - if (pchan->parent) { - /* bone transform itself */ - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + /* If we're adding to an action, we will have groups to write to... */ + if (groups && grpname) { + /* wrap the pointers given into a dummy action that we pass to the API func + * and extract the resultant lists... + */ + bAction tmp_act; + bActionGroup *agrp= NULL; - /* The bone's root offset (is in the parent's coordinate system) */ - VECCOPY(offs_bone[3], pchan->bone->head); + /* init the temp action */ + //memset(&tmp_act, 0, sizeof(bAction)); // XXX only enable this line if we get errors + tmp_act.groups.first= groups->first; + tmp_act.groups.last= groups->last; + tmp_act.curves.first= list->first; + tmp_act.curves.last= list->last; + /* ... xxx, the other vars don't need to be filled in */ - /* Get the length translation of parent (length along y axis) */ - offs_bone[3][1]+= pchan->parent->bone->length; + /* get the group to use */ + agrp= action_groups_find_named(&tmp_act, grpname); + if (agrp == NULL) { + /* no matching group, so add one */ + if (agrp == NULL) { + /* Add a new group, and make it active */ + agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup"); + + agrp->flag = AGRP_SELECTED; + BLI_snprintf(agrp->name, 64, grpname); + + BLI_addtail(&tmp_act.groups, agrp); + BLI_uniquename(&tmp_act.groups, agrp, "Group", '.', offsetof(bActionGroup, name), 64); + } + } - Mat4MulSerie(parmat, pchan->parent->pose_mat, offs_bone, NULL, NULL, NULL, NULL, NULL, NULL); + /* add F-Curve to group */ + /* WARNING: this func should only need to look at the stuff we initialised, if not, things may crash */ + action_groups_add_channel(&tmp_act, agrp, fcu); - /* invert it */ - Mat4Invert(imat, parmat); + /* set the output lists based on the ones in the temp action */ + groups->first= tmp_act.groups.first; + groups->last= tmp_act.groups.last; + list->first= tmp_act.curves.first; + list->last= tmp_act.curves.last; } else { - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); - VECCOPY(offs_bone[3], pchan->bone->head); - - /* invert it */ - Mat4Invert(imat, offs_bone); + /* simply add the F-Curve to the end of the given list */ + BLI_addtail(list, fcu); } - - /* difference: current transform - (parent transform + bone transform) */ - Mat4MulMat4(diff_mat, pchan->pose_mat, imat); - - /* extract relevant components */ - if (loc) - VECCOPY(loc, diff_mat[3]); - if (eul) - Mat4ToEul(diff_mat, eul); - if (size) - Mat4ToSize(diff_mat, size); } -/* evaluate an IPO-driver to get a 'time' value to use instead of "ipotime" - * - "ipotime" is the frame at which IPO-curve is being evaluated - * - has to return a float value +/* Convert IPO-Curve to F-Curve (including Driver data), and free any of the old data that + * is not relevant, BUT do not free the IPO-Curve itself... + * actname: name of Action-Channel (if applicable) that IPO-Curve's IPO-block belonged to + * constname: name of Constraint-Channel (if applicable) that IPO-Curve's IPO-block belonged to */ -static float eval_driver (IpoDriver *driver, float ipotime) +static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, char *actname, char *constname) { -#ifndef DISABLE_PYTHON - /* currently, drivers are either PyDrivers (evaluating a PyExpression, or Object/Pose-Channel transforms) */ - if (driver->type == IPO_DRIVER_TYPE_PYTHON) { - /* check for empty or invalid expression */ - if ( (driver->name[0] == '\0') || - (driver->flag & IPO_DRIVER_FLAG_INVALID) ) + AdrBit2Path *abp; + FCurve *fcu; + int i=0, totbits; + + /* allocate memory for a new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "FCurve"); + + /* convert driver - will free the old one... */ + if (icu->driver) { + fcu->driver= idriver_to_cdriver(icu->driver); + icu->driver= NULL; + } + + /* copy flags */ + if (icu->flag & IPO_VISIBLE) fcu->flag |= FCURVE_VISIBLE; + if (icu->flag & IPO_SELECT) fcu->flag |= FCURVE_SELECTED; + if (icu->flag & IPO_ACTIVE) fcu->flag |= FCURVE_ACTIVE; + if (icu->flag & IPO_MUTE) fcu->flag |= FCURVE_MUTED; + if (icu->flag & IPO_PROTECT) fcu->flag |= FCURVE_PROTECTED; + if (icu->flag & IPO_AUTO_HORIZ) fcu->flag |= FCURVE_AUTO_HANDLES; + + /* set extrapolation */ + switch (icu->extrap) { + case IPO_HORIZ: /* constant extrapolation */ + case IPO_DIR: /* linear extrapolation */ { - return 0.0f; + /* just copy, as the new defines match the old ones... */ + fcu->extend= icu->extrap; } - - /* this evaluates the expression using Python,and returns its result: - * - on errors it reports, then returns 0.0f - */ - return BPY_pydriver_eval(driver); - } - else -#endif /* DISABLE_PYTHON */ - { - - Object *ob= driver->ob; - - /* must have an object to evaluate */ - if (ob == NULL) - return 0.0f; - - /* if a proxy, use the proxy source*/ - if (ob->proxy_from) - ob= ob->proxy_from; - - /* use given object as driver */ - if (driver->blocktype == ID_OB) { - /* depsgraph failure: ob ipos are calculated in where_is_object, this might get called too late */ - if ((ob->ipo) && (ob->ctime != ipotime)) { - /* calculate the value of relevant channel on the Object, but do not write the value - * calculated on to the Object but onto "ipotime" instead - */ - calc_ipo_spec(ob->ipo, driver->adrcode, &ipotime); - return ipotime; - } + break; - /* return the value of the relevant channel */ - switch (driver->adrcode) { - case OB_LOC_X: - return ob->loc[0]; - case OB_LOC_Y: - return ob->loc[1]; - case OB_LOC_Z: - return ob->loc[2]; - case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[0]/(M_PI_2/9.0) ); - case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[1]/(M_PI_2/9.0) ); - case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[2]/(M_PI_2/9.0) ); - case OB_SIZE_X: - return ob->size[0]; - case OB_SIZE_Y: - return ob->size[1]; - case OB_SIZE_Z: - return ob->size[2]; - } + case IPO_CYCL: /* cyclic extrapolation */ + case IPO_CYCLX: /* cyclic extrapolation + offset */ + { + /* Add a new FModifier (Cyclic) instead of setting extend value + * as that's the new equivilant of that option. + */ + FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES); + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + + /* if 'offset' one is in use, set appropriate settings */ + if (icu->extrap == IPO_CYCLX) + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC_OFFSET; + else + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; } + break; + } + + /* -------- */ + + /* get adrcode <-> bitflags mapping to handle nasty bitflag curves? */ + abp= adrcode_bitmaps_to_paths(icu->blocktype, icu->adrcode, &totbits); + if (abp && totbits) { + FCurve *fcurve; + int b; + + if (G.f & G_DEBUG) printf("\tconvert bitflag ipocurve, totbits = %d \n", totbits); + + /* add the 'only int values' flag */ + fcu->flag |= (FCURVE_INT_VALUES|FCURVE_DISCRETE_VALUES); - /* use given pose-channel as driver */ - else { /* ID_AR */ - bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name); + /* for each bit we have to remap + check for: + * 1) we need to make copy the existing F-Curve data (fcu -> fcurve), + * except for the last one which will use the original + * 2) copy the relevant path info across + * 3) filter the keyframes for the flag of interest + */ + for (b=0; b < totbits; b++, abp++) { + /* make a copy of existing base-data if not the last curve */ + if (b < (totbits-1)) + fcurve= copy_fcurve(fcu); + else + fcurve= fcu; + + /* set path */ + fcurve->rna_path= BLI_strdupn(abp->path, strlen(abp->path)); + fcurve->array_index= abp->array_index; - /* must have at least 1 bone to use */ - if (pchan && pchan->bone) { - /* rotation difference is not a simple driver (i.e. value drives value), but the angle between 2 bones is driving stuff... - * - the name of the second pchan is also stored in driver->name, but packed after the other one by DRIVER_NAME_OFFS chars - */ - if (driver->adrcode == OB_ROT_DIFF) { - bPoseChannel *pchan2= get_pose_channel(ob->pose, driver->name+DRIVER_NAME_OFFS); - - if (pchan2 && pchan2->bone) { - float q1[4], q2[4], quat[4], angle; - - Mat4ToQuat(pchan->pose_mat, q1); - Mat4ToQuat(pchan2->pose_mat, q2); - - QuatInv(q1); - QuatMul(quat, q1, q2); - angle = 2.0f * (saacos(quat[0])); - angle= ABS(angle); - - return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle); - } - } + /* convert keyframes + * - beztriples and bpoints are mutually exclusive, so we won't have both at the same time + * - beztriples are more likely to be encountered as they are keyframes (the other type wasn't used yet) + */ + fcurve->totvert= icu->totvert; + + if (icu->bezt) { + BezTriple *dst, *src; + + /* allocate new array for keyframes/beztriples */ + fcurve->bezt= MEM_callocN(sizeof(BezTriple)*fcurve->totvert, "BezTriples"); - /* standard driver */ - else { - float loc[3], eul[3], size[3]; + /* loop through copying all BezTriples individually, as we need to modify a few things */ + for (dst=fcurve->bezt, src=icu->bezt; i < fcurve->totvert; i++, dst++, src++) { + /* firstly, copy BezTriple data */ + *dst= *src; - /* retrieve local transforms to return - * - we use eulers here NOT quats, so that Objects can be driven by bones easily - * also, this way is more understandable for users - */ - posechannel_get_local_transform(pchan, loc, eul, size); + /* interpolation can only be constant... */ + dst->ipo= BEZT_IPO_CONST; - switch (driver->adrcode) { - case OB_LOC_X: - return loc[0]; - case OB_LOC_Y: - return loc[1]; - case OB_LOC_Z: - return loc[2]; - case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[0]/(M_PI_2/9.0) ); - case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[1]/(M_PI_2/9.0) ); - case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[2]/(M_PI_2/9.0) ); - case OB_SIZE_X: - return size[0]; - case OB_SIZE_Y: - return size[1]; - case OB_SIZE_Z: - return size[2]; - } + /* correct values, by checking if the flag of interest is set */ + if ( ((int)(dst->vec[1][1])) & (abp->bit) ) + dst->vec[0][1]= dst->vec[1][1]= dst->vec[2][1] = 1.0f; + else + dst->vec[0][1]= dst->vec[1][1]= dst->vec[2][1] = 0.0f; } } - } - } - - /* return 0.0f, as couldn't find relevant data to use */ - return 0.0f; -} - -/* evaluate and return the value of the given IPO-curve at the specified frame ("evaltime") */ -float eval_icu(IpoCurve *icu, float evaltime) -{ - float cvalue = 0.0f; - - /* if there is a driver, evaluate it to find value to use as "evaltime" - * - this value will also be returned as the value of the 'curve', if there are no keyframes - */ - if (icu->driver) { - /* ipotime now serves as input for the curve */ - evaltime= cvalue= eval_driver(icu->driver, evaltime); - } - - /* there are keyframes (in the form of BezTriples) which can be interpolated between */ - if (icu->bezt) { - /* get pointers */ - BezTriple *bezt, *prevbezt, *lastbezt; - float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; - float cycdx, cycdy, ofs, cycyofs= 0.0; - int a, b; - - /* get pointers */ - a= icu->totvert-1; - prevbezt= icu->bezt; - bezt= prevbezt+1; - lastbezt= prevbezt + a; - - /* extrapolation mode is 'cyclic' - find relative place within a cycle */ - if (icu->extrap & IPO_CYCL) { - /* ofs is start frame of cycle */ - ofs= prevbezt->vec[1][0]; - - /* calculate period and amplitude (total height) of a cycle */ - cycdx= lastbezt->vec[1][0] - prevbezt->vec[1][0]; - cycdy= lastbezt->vec[1][1] - prevbezt->vec[1][1]; - - /* cycle occurs over some period of time (cycdx should be positive all the time) */ - if (cycdx) { - /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle - * - IPO_CYCLX = (IPO_CYCL + IPO_DIR) - */ - if (icu->extrap & IPO_DIR) { - cycyofs = (float)floor((evaltime - ofs) / cycdx); - cycyofs *= cycdy; - } - - /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ - evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); - if (evaltime < ofs) evaltime += cycdx; + else if (icu->bp) { + /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */ + //BPoint *bp; + //FPoint *fpt; } + + /* add new F-Curve to list */ + fcurve_add_to_list(groups, list, fcurve, actname); } - /* evaluation time at or past endpoints? */ - // TODO: for per-bezt interpolation, replace all icu->ipo with (bezt)->ipo - if (prevbezt->vec[1][0] >= evaltime) { - /* before or on first keyframe */ - if ((icu->extrap & IPO_DIR) && (icu->ipo != IPO_CONST)) { - /* linear or bezier interpolation */ - if (icu->ipo==IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (icu->totvert == 1) - cvalue= prevbezt->vec[1][1]; - else { - bezt = prevbezt+1; - dx= prevbezt->vec[1][0] - evaltime; - fac= bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue= prevbezt->vec[1][1] - (fac * dx); - } - else - cvalue= prevbezt->vec[1][1]; - } - } - else { - /* Use the first handle (earlier) of first BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx= prevbezt->vec[1][0] - evaltime; - fac= prevbezt->vec[1][0] - prevbezt->vec[0][0]; + /* free old data of curve now that it's no longer needed for converting any more curves */ + if (icu->bezt) MEM_freeN(icu->bezt); + if (icu->bp) MEM_freeN(icu->bezt); + } + else { + /* get rna-path + * - we will need to set the 'disabled' flag if no path is able to be made (for now) + */ + fcu->rna_path= get_rna_access(icu->blocktype, icu->adrcode, actname, constname, &fcu->array_index); + if (fcu->rna_path == NULL) + fcu->flag |= FCURVE_DISABLED; + + /* convert keyframes + * - beztriples and bpoints are mutually exclusive, so we won't have both at the same time + * - beztriples are more likely to be encountered as they are keyframes (the other type wasn't used yet) + */ + fcu->totvert= icu->totvert; + + if (icu->bezt) { + BezTriple *dst, *src; + + /* allocate new array for keyframes/beztriples */ + fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples"); + + /* loop through copying all BezTriples individually, as we need to modify a few things */ + for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) { + /* firstly, copy BezTriple data */ + *dst= *src; + + /* now copy interpolation from curve (if not already set) */ + if (icu->ipo != IPO_MIXED) + dst->ipo= icu->ipo; - /* prevent division by zero */ - if (fac) { - fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; - cvalue= prevbezt->vec[1][1] - (fac * dx); - } - else - cvalue= prevbezt->vec[1][1]; - } - } - else { - /* constant (IPO_HORIZ) extrapolation or constant interpolation, - * so just extend first keyframe's value - */ - cvalue= prevbezt->vec[1][1]; - } - } - else if (lastbezt->vec[1][0] <= evaltime) { - /* after or on last keyframe */ - if( (icu->extrap & IPO_DIR) && (icu->ipo != IPO_CONST)) { - /* linear or bezier interpolation */ - if (icu->ipo==IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (icu->totvert == 1) - cvalue= lastbezt->vec[1][1]; - else { - prevbezt = lastbezt - 1; - dx= evaltime - lastbezt->vec[1][0]; - fac= lastbezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue= lastbezt->vec[1][1] + (fac * dx); - } - else - cvalue= lastbezt->vec[1][1]; - } - } - else { - /* Use the gradient of the second handle (later) of last BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx= evaltime - lastbezt->vec[1][0]; - fac= lastbezt->vec[2][0] - lastbezt->vec[1][0]; + /* correct values for euler rotation curves - they were degrees/10 */ + // XXX for now, just make them into radians as RNA sets/reads directly in that form + if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) || + ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) ) + { + const float fac= (float)M_PI / 18.0f; //10.0f * M_PI/180.0f; - /* prevent division by zero */ - if (fac) { - fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; - cvalue= lastbezt->vec[1][1] + (fac * dx); - } - else - cvalue= lastbezt->vec[1][1]; + dst->vec[0][1] *= fac; + dst->vec[1][1] *= fac; + dst->vec[2][1] *= fac; } } - else { - /* constant (IPO_HORIZ) extrapolation or constant interpolation, - * so just extend last keyframe's value - */ - cvalue= lastbezt->vec[1][1]; - } + + /* free this data now */ + MEM_freeN(icu->bezt); } - else { - /* evaltime occurs somewhere in the middle of the curve */ - // TODO: chould be optimised by using a binary search instead??? - for (a=0; prevbezt && bezt && (a < icu->totvert-1); a++, prevbezt=bezt, bezt++) { - /* evaltime occurs within the interval defined by these two keyframes */ - if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) { - /* value depends on interpolation mode */ - if (icu->ipo == IPO_CONST) { - /* constant (evaltime not relevant, so no interpolation needed) */ - cvalue= prevbezt->vec[1][1]; - } - else if (icu->ipo == IPO_LIN) { - /* linear - interpolate between values of the two keyframes */ - fac= bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac= (evaltime - prevbezt->vec[1][0]) / fac; - cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1])); - } - else - cvalue= prevbezt->vec[1][1]; - } - else { - /* bezier interpolation */ - /* v1,v2 are the first keyframe and its 2nd handle */ - v1[0]= prevbezt->vec[1][0]; - v1[1]= prevbezt->vec[1][1]; - v2[0]= prevbezt->vec[2][0]; - v2[1]= prevbezt->vec[2][1]; - /* v3,v4 are the last keyframe's 1st handle + the last keyframe */ - v3[0]= bezt->vec[0][0]; - v3[1]= bezt->vec[0][1]; - v4[0]= bezt->vec[1][0]; - v4[1]= bezt->vec[1][1]; - - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue= opl[0]; - break; - } - } - } - } + else if (icu->bp) { + /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */ + //BPoint *bp; + //FPoint *fpt; } - /* apply y-offset (for 'cyclic extrapolation') to calculated value */ - cvalue+= cycyofs; + /* add new F-Curve to list */ + fcurve_add_to_list(groups, list, fcu, actname); } - - /* clamp evaluated value to lie within allowable value range for this channel */ - if (icu->ymin < icu->ymax) { - CLAMP(cvalue, icu->ymin, icu->ymax); - } - - /* return evaluated value */ - return cvalue; } -/* ------------------- IPO-Block/Curve Calculation - General API ----------------------- */ - -/* calculate the value of the given IPO-curve at the current frame, and set its curval */ -void calc_icu (IpoCurve *icu, float ctime) -{ - /* calculate and set curval (evaluates driver too) */ - icu->curval= eval_icu(icu, ctime); -} +/* ------------------------- */ -/* calculate for the current frame, all IPO-curves in IPO-block that can be evaluated - * - icu->curval is set for all IPO-curves which are evaluated! +/* Convert IPO-block (i.e. all its IpoCurves) to the new system. + * This does not assume that any ID or AnimData uses it, but does assume that + * it is given two lists, which it will perform driver/animation-data separation. */ -void calc_ipo (Ipo *ipo, float ctime) +static void ipo_to_animato (Ipo *ipo, char actname[], char constname[], ListBase *animgroups, ListBase *anim, ListBase *drivers) { - IpoCurve *icu; - - /* if there is no IPO block to evaluate, or whole block is "muted" */ - if (ipo == NULL) return; - if (ipo->muteipo) return; - - /* loop over all curves */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - /* only evaluated curve if allowed to: - * - Muted channels should not be evaluated as they shouldn't have any effect - * --> user explictly turned them off! - * - Drivers should be evaluated at all updates - * --> TODO Note: drivers should be separated from standard channels - * - IPO_LOCK is not set, as it is set by some internal mechanisms to prevent - * IPO-curve from overwriting data (currently only used for IPO-Record). - */ - if ((icu->driver) || (icu->flag & IPO_LOCK)==0) { - if ((icu->flag & IPO_MUTE)==0) - calc_icu(icu, ctime); - } - } -} - -/* ------------------- IPO-Block/Curve Calculation - Special Hacks ----------------------- */ - -/* Calculate and return the value of the 'Time' Ipo-Curve from an Object, - * OR return the current time if not found - * - used in object.c -> bsystem_time() - */ -float calc_ipo_time (Ipo *ipo, float ctime) -{ - /* only Time IPO from Object IPO-blocks are relevant */ - if ((ipo) && (ipo->blocktype == ID_OB)) { - IpoCurve *icu= find_ipocurve(ipo, OB_TIME); - - /* only calculate (and set icu->curval) for time curve */ - if (icu) { - calc_icu(icu, ctime); - return (10.0f * icu->curval); - } - } - - /* no appropriate time-curve found */ - return ctime; -} - -/* Evaluate the specified channel in the given IPO block on the specified frame (ctime), - * writing the value into that channel's icu->curval, but ALSO dumping it in ctime. - * - Returns success and modifies ctime! - */ -short calc_ipo_spec (Ipo *ipo, int adrcode, float *ctime) -{ - IpoCurve *icu= find_ipocurve(ipo, adrcode); + IpoCurve *icu, *icn; - /* only evaluate if found */ - if (icu) { - /* only calculate if allowed to (not locked and not muted) - * - drivers not taken into account, because this may be called when calculating a driver - */ - if ((icu->flag & (IPO_LOCK|IPO_MUTE))==0) - calc_icu(icu, *ctime); + /* sanity check */ + if (ELEM3(NULL, ipo, anim, drivers)) + return; + + if (G.f & G_DEBUG) printf("ipo_to_animato \n"); - /* value resulting from calculations is written into ctime! */ - *ctime= icu->curval; - return 1; + /* validate actname and constname + * - clear actname if it was one of the generic <builtin> ones (i.e. 'Object', or 'Shapes') + * - actname can then be used to assign F-Curves in Action to Action Groups + * (i.e. thus keeping the benefits that used to be provided by Action Channels for grouping + * F-Curves for bones). This may be added later... for now let's just dump without them... + */ + if (actname) { + if ((ipo->blocktype == ID_OB) && (strcmp(actname, "Object") == 0)) + actname= NULL; + else if ((ipo->blocktype == ID_OB) && (strcmp(actname, "Shape") == 0)) + actname= NULL; } - /* couldn't evaluate */ - return 0; -} - -/* ***************************** IPO - DataAPI ********************************* */ - -/* --------------------- Flush/Execute IPO Values ----------------------------- */ - -/* Flush IpoCurve->curvals to the data they affect (defined by ID) - * - not for Actions or Constraints! (those have their own special handling) - */ -void execute_ipo (ID *id, Ipo *ipo) -{ - IpoCurve *icu; - void *poin; - int type; - - /* don't do anything without an IPO block */ - if (ipo == NULL) - return; - - /* loop over IPO Curves, getting pointer to var to affect, and write into that pointer */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - poin= get_ipo_poin(id, icu, &type); - if (poin) write_ipo_poin(poin, type, icu->curval); - } -} - -/* Flush Action-Channel IPO data to Pose Channel */ -void execute_action_ipo (bActionChannel *achan, bPoseChannel *pchan) -{ - /* only do this if there's an Action Channel and Pose Channel to use */ - if (achan && achan->ipo && pchan) { - IpoCurve *icu; + /* loop over IPO-Curves, freeing as we progress */ + for (icu= ipo->curve.first; icu; icu= icn) { + /* get link to next (for later) */ + icn= icu->next; - /* loop over IPO-curves, getting a pointer to pchan var to write to - * - assume for now that only 'float' channels will ever get written into + /* Since an IPO-Curve may end up being made into many F-Curves (i.e. bitflag curves), + * we figure out the best place to put the channel, then tell the curve-converter to just dump there */ - for (icu= achan->ipo->curve.first; icu; icu= icu->next) { - void *poin= get_pchan_ipo_poin(pchan, icu->adrcode); - if (poin) write_ipo_poin(poin, IPO_FLOAT, icu->curval); + if (icu->driver) { + /* Blender 2.4x allowed empty drivers, but we don't now, since they cause more trouble than they're worth */ + if ((icu->driver->ob) || (icu->driver->type == IPO_DRIVER_TYPE_PYTHON)) + icu_to_fcurves(NULL, drivers, icu, actname, constname); + else + MEM_freeN(icu->driver); } - } -} - - -/* --------------------- Force Calculation + Flush IPO Values ----------------------------- */ - -/* Calculate values for given IPO block, then flush to all of block's users - * - for general usage - */ -void do_ipo (Ipo *ipo) -{ - if (ipo) { - float ctime= frame_to_float(G.scene->r.cfra); + else + icu_to_fcurves(animgroups, anim, icu, actname, constname); - /* calculate values, then flush to all users of this IPO block */ - calc_ipo(ipo, ctime); - do_ipo_nocalc(ipo); + /* free this IpoCurve now that it's been converted */ + BLI_freelinkN(&ipo->curve, icu); } } -/* Calculate values for given Material's IPO block, then flush to given Material only */ -void do_mat_ipo (Material *ma) -{ - float ctime; - - if (ELEM(NULL, ma, ma->ipo)) - return; - - ctime= frame_to_float(G.scene->r.cfra); - /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */ - - /* calculate values for current time, then flush values to given material only */ - calc_ipo(ma->ipo, ctime); - execute_ipo((ID *)ma, ma->ipo); -} - -/* Calculate values for given Object's IPO block, then flush to given Object only - * - there's also some funky stuff that looks like it's for scene layers +/* Convert Action-block to new system, separating animation and drivers + * New curves may not be converted directly into the given Action (i.e. for Actions linked + * to Objects, where ob->ipo and ob->action need to be combined). + * NOTE: we need to be careful here, as same data-structs are used for new system too! */ -void do_ob_ipo (Object *ob) +static void action_to_animato (bAction *act, ListBase *groups, ListBase *curves, ListBase *drivers) { - float ctime; - unsigned int lay; + bActionChannel *achan, *achann; + bConstraintChannel *conchan, *conchann; - if (ob->ipo == NULL) + /* only continue if there are Action Channels (indicating unconverted data) */ + if (act->chanbase.first == NULL) return; - - /* do not set ob->ctime here: for example when parent in invisible layer */ - ctime= bsystem_time(ob, (float) G.scene->r.cfra, 0.0); - - /* calculate values of */ - calc_ipo(ob->ipo, ctime); - - /* Patch: remember localview */ - lay= ob->lay & 0xFF000000; - - /* flush IPO values to this object only */ - execute_ipo((ID *)ob, ob->ipo); - - /* hack: for layer animation??? - is this what this is? (Aligorith, 28Sep2008) */ - ob->lay |= lay; - if ((ob->id.name[2]=='S') && (ob->id.name[3]=='C') && (ob->id.name[4]=='E')) { - if (strcmp(G.scene->id.name+2, ob->id.name+6)==0) { - G.scene->lay= ob->lay; - copy_view3d_lock(0); - /* no redraw here! creates too many calls */ + + /* get rid of all Action Groups */ + // XXX this is risky if there's some old + some new data in the Action... + if (act->groups.first) + BLI_freelistN(&act->groups); + + /* loop through Action-Channels, converting data, freeing as we go */ + for (achan= act->chanbase.first; achan; achan= achann) { + /* get pointer to next Action Channel */ + achann= achan->next; + + /* convert Action Channel's IPO data */ + if (achan->ipo) { + ipo_to_animato(achan->ipo, achan->name, NULL, groups, curves, drivers); + achan->ipo->id.us--; + achan->ipo= NULL; } - } -} - -/* Only execute those IPO-Curves with drivers, on the current frame, for the given Object - * - TODO: Drivers should really be made separate from standard anim channels - */ -void do_ob_ipodrivers (Object *ob, Ipo *ipo, float ctime) -{ - IpoCurve *icu; - void *poin; - int type; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->driver) { - icu->curval= eval_icu(icu, ctime); + + /* convert constraint channel IPO-data */ + for (conchan= achan->constraintChannels.first; conchan; conchan= conchann) { + /* get pointer to next Constraint Channel */ + conchann= conchan->next; - poin= get_ipo_poin((ID *)ob, icu, &type); - if (poin) write_ipo_poin(poin, type, icu->curval); - } - } -} - -/* Special variation to calculate IPO values for Sequence + perform other stuff */ -void do_seq_ipo (Sequence *seq, int cfra) -{ - float ctime, div; - - /* seq_ipo has an exception: calc both fields immediately */ - if (seq->ipo) { - if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) { - ctime = frame_to_float(cfra); - div = 1.0; - } - else { - ctime= frame_to_float(cfra - seq->startdisp); - div= (seq->enddisp - seq->startdisp) / 100.0f; - if (div == 0.0) return; + /* convert Constraint Channel's IPO data */ + if (conchan->ipo) { + ipo_to_animato(conchan->ipo, achan->name, conchan->name, groups, curves, drivers); + conchan->ipo->id.us--; + conchan->ipo= NULL; + } + + /* free Constraint Channel */ + BLI_freelinkN(&achan->constraintChannels, conchan); } - /* 2nd field */ - calc_ipo(seq->ipo, (ctime+0.5f)/div); - execute_ipo((ID *)seq, seq->ipo); - seq->facf1= seq->facf0; - - /* 1st field */ - calc_ipo(seq->ipo, ctime/div); - execute_ipo((ID *)seq, seq->ipo); + /* free Action Channel */ + BLI_freelinkN(&act->chanbase, achan); } - else - seq->facf1= seq->facf0= 1.0f; } -/* --------- */ +/* ------------------------- */ -/* exception: it does calc for objects... - * now find out why this routine was used anyway! +/* Convert IPO-block (i.e. all its IpoCurves) for some ID to the new system + * This assumes that AnimData has been added already. Separation of drivers + * from animation data is accomplished here too... */ -void do_ipo_nocalc (Ipo *ipo) +static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[]) { - Object *ob; - Material *ma; - Tex *tex; - World *wo; - Lamp *la; - Camera *ca; - bSound *snd; - - if (ipo == NULL) - return; + AnimData *adt= BKE_animdata_from_id(id); + ListBase anim = {NULL, NULL}; + ListBase drivers = {NULL, NULL}; - /* only flush IPO values (without calculating first/again) on - * to the datablocks that use the given IPO block - */ - switch (ipo->blocktype) { - case ID_OB: - for (ob= G.main->object.first; ob; ob= ob->id.next) { - if (ob->ipo == ipo) do_ob_ipo(ob); - } - break; - case ID_MA: - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == ipo) execute_ipo((ID *)ma, ipo); - } - break; - case ID_TE: - for (tex= G.main->tex.first; tex; tex= tex->id.next) { - if (tex->ipo == ipo) execute_ipo((ID *)tex, ipo); - } - break; - case ID_WO: - for (wo= G.main->world.first; wo; wo= wo->id.next) { - if (wo->ipo == ipo) execute_ipo((ID *)wo, ipo); - } - break; - case ID_LA: - for (la= G.main->lamp.first; la; la= la->id.next) { - if (la->ipo == ipo) execute_ipo((ID *)la, ipo); - } - break; - case ID_CA: - for (ca= G.main->camera.first; ca; ca= ca->id.next) { - if (ca->ipo == ipo) execute_ipo((ID *)ca, ipo); - } - break; - case ID_SO: - for (snd= G.main->sound.first; snd; snd= snd->id.next) { - if (snd->ipo == ipo) execute_ipo((ID *)snd, ipo); - } - break; + /* sanity check */ + if ELEM(NULL, id, ipo) + return; + if (adt == NULL) { + printf("ERROR ipo_to_animdata(): adt invalid \n"); + return; } -} - -/* Executes IPO's for whole database on frame change, in a specified order, - * with datablocks being calculated in alphabetical order - * - called on scene_update_for_newframe() only - */ -void do_all_data_ipos () -{ - Material *ma; - Tex *tex; - World *wo; - Ipo *ipo; - Lamp *la; - Key *key; - Camera *ca; - bSound *snd; - Sequence *seq; - Editing *ed; - Base *base; - float ctime; - - ctime= frame_to_float(G.scene->r.cfra); - /* this exception cannot be depgraphed yet... what todo with objects in other layers?... */ - for (base= G.scene->base.first; base; base= base->next) { - Object *ob= base->object; - - /* only update layer when an ipo */ - if (has_ipo_code(ob->ipo, OB_LAY)) { - do_ob_ipo(ob); - base->lay= ob->lay; - } + if (G.f & G_DEBUG) { + printf("ipo to animdata - ID:%s, IPO:%s, actname:%s constname:%s curves:%d \n", + id->name+2, ipo->id.name+2, (actname)?actname:"<None>", (constname)?constname:"<None>", + BLI_countlist(&ipo->curve)); } - /* layers for the set...*/ - if (G.scene->set) { - for (base= G.scene->set->base.first; base; base= base->next) { - Object *ob= base->object; - - if (has_ipo_code(ob->ipo, OB_LAY)) { - do_ob_ipo(ob); - base->lay= ob->lay; - } - } - } + /* Convert curves to animato system (separated into separate lists of F-Curves for animation and drivers), + * and the try to put these lists in the right places, but do not free the lists here + */ + // XXX there shouldn't be any need for the groups, so don't supply pointer for that now... + ipo_to_animato(ipo, actname, constname, NULL, &anim, &drivers); - /* Calculate all IPO blocks in use, execept those for Objects */ - for (ipo= G.main->ipo.first; ipo; ipo= ipo->id.next) { - if ((ipo->id.us) && (ipo->blocktype != ID_OB)) { - calc_ipo(ipo, ctime); + /* deal with animation first */ + if (anim.first) { + if (G.f & G_DEBUG) printf("\thas anim \n"); + /* try to get action */ + if (adt->action == NULL) { + adt->action= add_empty_action("ConvData_Action"); // XXX we need a better name for this + if (G.f & G_DEBUG) printf("\t\tadded new action \n"); } - } - - /* Texture Blocks */ - for (tex= G.main->tex.first; tex; tex= tex->id.next) { - if (tex->ipo) execute_ipo((ID *)tex, tex->ipo); - } - - /* Material Blocks */ - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo) execute_ipo((ID *)ma, ma->ipo); - } - - /* World Blocks */ - for (wo= G.main->world.first; wo; wo= wo->id.next) { - if (wo->ipo) execute_ipo((ID *)wo, wo->ipo); - } - - /* ShapeKey Blocks */ - for (key= G.main->key.first; key; key= key->id.next) { - if (key->ipo) execute_ipo((ID *)key, key->ipo); - } - - /* Lamp Blocks */ - for (la= G.main->lamp.first; la; la= la->id.next) { - if (la->ipo) execute_ipo((ID *)la, la->ipo); - } - - /* Camera Blocks */ - for (ca= G.main->camera.first; ca; ca= ca->id.next) { - if (ca->ipo) execute_ipo((ID *)ca, ca->ipo); + + /* add F-Curves to action */ + addlisttolist(&adt->action->curves, &anim); } - /* Sound Blocks (Old + Unused) */ - for (snd= G.main->sound.first; snd; snd= snd->id.next) { - if (snd->ipo) execute_ipo((ID *)snd, snd->ipo); - } - - /* Sequencer: process FAC Ipos used as volume envelopes */ - ed= G.scene->ed; - if (ed) { - for (seq= ed->seqbasep->first; seq; seq= seq->next) { - if ( ((seq->type == SEQ_RAM_SOUND) || (seq->type == SEQ_HD_SOUND)) && - (seq->startdisp <= G.scene->r.cfra+2) && - (seq->enddisp>G.scene->r.cfra) && - (seq->ipo) ) - { - do_seq_ipo(seq, G.scene->r.cfra); - } - } + /* deal with drivers */ + if (drivers.first) { + if (G.f & G_DEBUG) printf("\thas drivers \n"); + /* add drivers to end of driver stack */ + addlisttolist(&adt->drivers, &drivers); } } - -/* --------------------- Assorted ----------------------------- */ - -/* clear delta-transforms on all Objects which use the given IPO block */ -void clear_delta_obipo(Ipo *ipo) +/* Convert Action-block to new system + * NOTE: we need to be careful here, as same data-structs are used for new system too! + */ +static void action_to_animdata (ID *id, bAction *act) { - Object *ob; + AnimData *adt= BKE_animdata_from_id(id); - /* only search if there's an IPO */ - if (ipo == NULL) + /* only continue if there are Action Channels (indicating unconverted data) */ + if (ELEM(NULL, adt, act->chanbase.first)) return; - /* search through all objects in database */ - for (ob= G.main->object.first; ob; ob= ob->id.next) { - /* can only update if not a library */ - if (ob->id.lib == NULL) { - if (ob->ipo == ipo) { - memset(&ob->dloc, 0, 12); - memset(&ob->drot, 0, 12); - memset(&ob->dsize, 0, 12); - } - } + /* check if we need to set this Action as the AnimData's action */ + if (adt->action == NULL) { + /* set this Action as AnimData's Action */ + if (G.f & G_DEBUG) printf("act_to_adt - set adt action to act \n"); + adt->action= act; } + + /* convert Action data */ + action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers); } -/* ***************************** IPO - DataAPI ********************************* */ +/* *************************************************** */ +/* External API - Only Called from do_versions() */ -// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!! - -/* These functions here should be replaced eventually by the Data API, as this is - * inflexible duplication... +/* Called from do_versions() in readfile.c to convert the old 'IPO/adrcode' system + * to the new 'Animato/RNA' system. + * + * The basic method used here, is to loop over datablocks which have IPO-data, and + * add those IPO's to new AnimData blocks as Actions. + * Action/NLA data only works well for Objects, so these only need to be checked for there. + * + * Data that has been converted should be freed immediately, which means that it is immediately + * clear which datablocks have yet to be converted, and also prevent freeing errors when we exit. */ - -/* --------------------- Get Pointer API ----------------------------- */ - -/* get pointer to pose-channel's channel, but set appropriate flags first */ -void *get_pchan_ipo_poin (bPoseChannel *pchan, int adrcode) +// XXX currently done after all file reading... +void do_versions_ipos_to_animato(Main *main) { - void *poin= NULL; - - switch (adrcode) { - case AC_QUAT_W: - poin= &(pchan->quat[0]); - pchan->flag |= POSE_ROT; - break; - case AC_QUAT_X: - poin= &(pchan->quat[1]); - pchan->flag |= POSE_ROT; - break; - case AC_QUAT_Y: - poin= &(pchan->quat[2]); - pchan->flag |= POSE_ROT; - break; - case AC_QUAT_Z: - poin= &(pchan->quat[3]); - pchan->flag |= POSE_ROT; - break; - - case AC_LOC_X: - poin= &(pchan->loc[0]); - pchan->flag |= POSE_LOC; - break; - case AC_LOC_Y: - poin= &(pchan->loc[1]); - pchan->flag |= POSE_LOC; - break; - case AC_LOC_Z: - poin= &(pchan->loc[2]); - pchan->flag |= POSE_LOC; - break; - - case AC_SIZE_X: - poin= &(pchan->size[0]); - pchan->flag |= POSE_SIZE; - break; - case AC_SIZE_Y: - poin= &(pchan->size[1]); - pchan->flag |= POSE_SIZE; - break; - case AC_SIZE_Z: - poin= &(pchan->size[2]); - pchan->flag |= POSE_SIZE; - break; - } + ListBase drivers = {NULL, NULL}; + ID *id; + AnimData *adt; - /* return pointer */ - return poin; -} - -/* get texture channel */ -static void *give_tex_poin (Tex *tex, int adrcode, int *type ) -{ - void *poin= NULL; - - switch (adrcode) { - case TE_NSIZE: - poin= &(tex->noisesize); break; - case TE_TURB: - poin= &(tex->turbul); break; - case TE_NDEPTH: - poin= &(tex->noisedepth); *type= IPO_SHORT; break; - case TE_NTYPE: - poin= &(tex->noisetype); *type= IPO_SHORT; break; - case TE_VNW1: - poin= &(tex->vn_w1); break; - case TE_VNW2: - poin= &(tex->vn_w2); break; - case TE_VNW3: - poin= &(tex->vn_w3); break; - case TE_VNW4: - poin= &(tex->vn_w4); break; - case TE_VNMEXP: - poin= &(tex->vn_mexp); break; - case TE_ISCA: - poin= &(tex->ns_outscale); break; - case TE_DISTA: - poin= &(tex->dist_amount); break; - case TE_VN_COLT: - poin= &(tex->vn_coltype); *type= IPO_SHORT; break; - case TE_VN_DISTM: - poin= &(tex->vn_distm); *type= IPO_SHORT; break; - case TE_MG_TYP: - poin= &(tex->stype); *type= IPO_SHORT; break; - case TE_MGH: - poin= &(tex->mg_H); break; - case TE_MG_LAC: - poin= &(tex->mg_lacunarity); break; - case TE_MG_OCT: - poin= &(tex->mg_octaves); break; - case TE_MG_OFF: - poin= &(tex->mg_offset); break; - case TE_MG_GAIN: - poin= &(tex->mg_gain); break; - case TE_N_BAS1: - poin= &(tex->noisebasis); *type= IPO_SHORT; break; - case TE_N_BAS2: - poin= &(tex->noisebasis2); *type= IPO_SHORT; break; - case TE_COL_R: - poin= &(tex->rfac); break; - case TE_COL_G: - poin= &(tex->gfac); break; - case TE_COL_B: - poin= &(tex->bfac); break; - case TE_BRIGHT: - poin= &(tex->bright); break; - case TE_CONTRA: - poin= &(tex->contrast); break; + if (main == NULL) { + printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n"); + return; } - - /* return pointer */ - return poin; -} - -/* get texture-slot/mapping channel */ -void *give_mtex_poin (MTex *mtex, int adrcode) -{ - void *poin= NULL; - - switch (adrcode) { - case MAP_OFS_X: - poin= &(mtex->ofs[0]); break; - case MAP_OFS_Y: - poin= &(mtex->ofs[1]); break; - case MAP_OFS_Z: - poin= &(mtex->ofs[2]); break; - case MAP_SIZE_X: - poin= &(mtex->size[0]); break; - case MAP_SIZE_Y: - poin= &(mtex->size[1]); break; - case MAP_SIZE_Z: - poin= &(mtex->size[2]); break; - case MAP_R: - poin= &(mtex->r); break; - case MAP_G: - poin= &(mtex->g); break; - case MAP_B: - poin= &(mtex->b); break; - case MAP_DVAR: - poin= &(mtex->def_var); break; - case MAP_COLF: - poin= &(mtex->colfac); break; - case MAP_NORF: - poin= &(mtex->norfac); break; - case MAP_VARF: - poin= &(mtex->varfac); break; - case MAP_DISP: - poin= &(mtex->dispfac); break; + + /* only convert if version is right */ + // XXX??? + if (main->versionfile >= 250) { + printf("WARNING: Animation data too new to convert (Version %d) \n", main->versionfile); + return; } - - /* return pointer */ - return poin; -} - -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - - -/* general function to get pointer to source/destination data */ -void *get_ipo_poin (ID *id, IpoCurve *icu, int *type) -{ - void *poin= NULL; - MTex *mtex= NULL; - - /* most channels will have float data, but those with other types will override this */ - *type= IPO_FLOAT; - - /* data is divided into 'blocktypes' based on ID-codes */ - switch (GS(id->name)) { - case ID_OB: /* object channels ----------------------------- */ - { - Object *ob= (Object *)id; - - switch (icu->adrcode) { - case OB_LOC_X: - poin= &(ob->loc[0]); break; - case OB_LOC_Y: - poin= &(ob->loc[1]); break; - case OB_LOC_Z: - poin= &(ob->loc[2]); break; - case OB_DLOC_X: - poin= &(ob->dloc[0]); break; - case OB_DLOC_Y: - poin= &(ob->dloc[1]); break; - case OB_DLOC_Z: - poin= &(ob->dloc[2]); break; - - case OB_ROT_X: - poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break; - case OB_ROT_Y: - poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break; - case OB_ROT_Z: - poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_X: - poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_Y: - poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_Z: - poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break; - - case OB_SIZE_X: - poin= &(ob->size[0]); break; - case OB_SIZE_Y: - poin= &(ob->size[1]); break; - case OB_SIZE_Z: - poin= &(ob->size[2]); break; - case OB_DSIZE_X: - poin= &(ob->dsize[0]); break; - case OB_DSIZE_Y: - poin= &(ob->dsize[1]); break; - case OB_DSIZE_Z: - poin= &(ob->dsize[2]); break; - - case OB_LAY: - poin= &(ob->lay); *type= IPO_INT_BIT; break; - - case OB_COL_R: - poin= &(ob->col[0]); break; - case OB_COL_G: - poin= &(ob->col[1]); break; - case OB_COL_B: - poin= &(ob->col[2]); break; - case OB_COL_A: - poin= &(ob->col[3]); break; - - case OB_PD_FSTR: - if (ob->pd) poin= &(ob->pd->f_strength); - break; - case OB_PD_FFALL: - if (ob->pd) poin= &(ob->pd->f_power); - break; - case OB_PD_SDAMP: - if (ob->pd) poin= &(ob->pd->pdef_damp); - break; - case OB_PD_RDAMP: - if (ob->pd) poin= &(ob->pd->pdef_rdamp); - break; - case OB_PD_PERM: - if (ob->pd) poin= &(ob->pd->pdef_perm); - break; - case OB_PD_FMAXD: - if (ob->pd) poin= &(ob->pd->maxdist); - break; - } - } - break; - case ID_MA: /* material channels ----------------------------- */ - { - Material *ma= (Material *)id; - - switch (icu->adrcode) { - case MA_COL_R: - poin= &(ma->r); break; - case MA_COL_G: - poin= &(ma->g); break; - case MA_COL_B: - poin= &(ma->b); break; - case MA_SPEC_R: - poin= &(ma->specr); break; - case MA_SPEC_G: - poin= &(ma->specg); break; - case MA_SPEC_B: - poin= &(ma->specb); break; - case MA_MIR_R: - poin= &(ma->mirr); break; - case MA_MIR_G: - poin= &(ma->mirg); break; - case MA_MIR_B: - poin= &(ma->mirb); break; - case MA_REF: - poin= &(ma->ref); break; - case MA_ALPHA: - poin= &(ma->alpha); break; - case MA_EMIT: - poin= &(ma->emit); break; - case MA_AMB: - poin= &(ma->amb); break; - case MA_SPEC: - poin= &(ma->spec); break; - case MA_HARD: - poin= &(ma->har); *type= IPO_SHORT; break; - case MA_SPTR: - poin= &(ma->spectra); break; - case MA_IOR: - poin= &(ma->ang); break; - case MA_MODE: - poin= &(ma->mode); *type= IPO_INT_BIT; break; // evil... dumping bitflags directly to user! - case MA_HASIZE: - poin= &(ma->hasize); break; - case MA_TRANSLU: - poin= &(ma->translucency); break; - case MA_RAYM: - poin= &(ma->ray_mirror); break; - case MA_FRESMIR: - poin= &(ma->fresnel_mir); break; - case MA_FRESMIRI: - poin= &(ma->fresnel_mir_i); break; - case MA_FRESTRA: - poin= &(ma->fresnel_tra); break; - case MA_FRESTRAI: - poin= &(ma->fresnel_tra_i); break; - case MA_ADD: - poin= &(ma->add); break; + else + printf("INFO: Converting to Animato... \n"); // xxx debug + + /* ----------- Animation Attached to Data -------------- */ + + /* objects */ + for (id= main->object.first; id; id= id->next) { + Object *ob= (Object *)id; + bPoseChannel *pchan; + bConstraint *con; + bConstraintChannel *conchan, *conchann; + + if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2); + + /* check if object has any animation data */ + if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* IPO first */ + if (ob->ipo) { + ipo_to_animdata(id, ob->ipo, NULL, NULL); + ob->ipo->id.us--; + ob->ipo= NULL; } - if (poin == NULL) { - if (icu->adrcode & MA_MAP1) mtex= ma->mtex[0]; - else if (icu->adrcode & MA_MAP2) mtex= ma->mtex[1]; - else if (icu->adrcode & MA_MAP3) mtex= ma->mtex[2]; - else if (icu->adrcode & MA_MAP4) mtex= ma->mtex[3]; - else if (icu->adrcode & MA_MAP5) mtex= ma->mtex[4]; - else if (icu->adrcode & MA_MAP6) mtex= ma->mtex[5]; - else if (icu->adrcode & MA_MAP7) mtex= ma->mtex[6]; - else if (icu->adrcode & MA_MAP8) mtex= ma->mtex[7]; - else if (icu->adrcode & MA_MAP9) mtex= ma->mtex[8]; - else if (icu->adrcode & MA_MAP10) mtex= ma->mtex[9]; - else if (icu->adrcode & MA_MAP12) mtex= ma->mtex[11]; - else if (icu->adrcode & MA_MAP11) mtex= ma->mtex[10]; - else if (icu->adrcode & MA_MAP13) mtex= ma->mtex[12]; - else if (icu->adrcode & MA_MAP14) mtex= ma->mtex[13]; - else if (icu->adrcode & MA_MAP15) mtex= ma->mtex[14]; - else if (icu->adrcode & MA_MAP16) mtex= ma->mtex[15]; - else if (icu->adrcode & MA_MAP17) mtex= ma->mtex[16]; - else if (icu->adrcode & MA_MAP18) mtex= ma->mtex[17]; + /* now Action */ + if (ob->action) { + action_to_animdata(id, ob->action); - if (mtex) - poin= give_mtex_poin(mtex, (icu->adrcode & (MA_MAP1-1))); + /* only decrease usercount if this Action isn't now being used by AnimData */ + if (ob->action != adt->action) { + ob->action->id.us--; + ob->action= NULL; + } } - } - break; - case ID_TE: /* texture channels ----------------------------- */ - { - Tex *tex= (Tex *)id; - - if (tex) - poin= give_tex_poin(tex, icu->adrcode, type); - } - break; - case ID_SEQ: /* sequence channels ----------------------------- */ - { - Sequence *seq= (Sequence *)id; - switch (icu->adrcode) { - case SEQ_FAC1: - poin= &(seq->facf0); break; - } + /* finally NLA */ + // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!) } - break; - case ID_CU: /* curve channels ----------------------------- */ - { - poin= &(icu->curval); - } - break; - case ID_KE: /* shapekey channels ----------------------------- */ - { - Key *key= (Key *)id; - KeyBlock *kb; + + /* check PoseChannels for constraints with local data */ + if (ob->pose) { + /* Verify if there's AnimData block */ + BKE_id_add_animdata(id); - for(kb= key->block.first; kb; kb= kb->next) { - if (kb->adrcode == icu->adrcode) - break; + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + for (con= pchan->constraints.first; con; con= con->next) { + /* if constraint has own IPO, convert add these to Object + * (NOTE: they're most likely to be drivers too) + */ + if (con->ipo) { + /* although this was the constraint's local IPO, we still need to provide pchan + con + * so that drivers can be added properly... + */ + ipo_to_animdata(id, con->ipo, pchan->name, con->name); + con->ipo->id.us--; + con->ipo= NULL; + } + } } - - if (kb) - poin= &(kb->curval); } - break; - case ID_WO: /* world channels ----------------------------- */ - { - World *wo= (World *)id; - - switch (icu->adrcode) { - case WO_HOR_R: - poin= &(wo->horr); break; - case WO_HOR_G: - poin= &(wo->horg); break; - case WO_HOR_B: - poin= &(wo->horb); break; - case WO_ZEN_R: - poin= &(wo->zenr); break; - case WO_ZEN_G: - poin= &(wo->zeng); break; - case WO_ZEN_B: - poin= &(wo->zenb); break; - - case WO_EXPOS: - poin= &(wo->exposure); break; - - case WO_MISI: - poin= &(wo->misi); break; - case WO_MISTDI: - poin= &(wo->mistdist); break; - case WO_MISTSTA: - poin= &(wo->miststa); break; - case WO_MISTHI: - poin= &(wo->misthi); break; - - case WO_STAR_R: - poin= &(wo->starr); break; - case WO_STAR_G: - poin= &(wo->starg); break; - case WO_STAR_B: - poin= &(wo->starb); break; - - case WO_STARDIST: - poin= &(wo->stardist); break; - case WO_STARSIZE: - poin= &(wo->starsize); break; - } - - if (poin == NULL) { - if (icu->adrcode & MA_MAP1) mtex= wo->mtex[0]; - else if (icu->adrcode & MA_MAP2) mtex= wo->mtex[1]; - else if (icu->adrcode & MA_MAP3) mtex= wo->mtex[2]; - else if (icu->adrcode & MA_MAP4) mtex= wo->mtex[3]; - else if (icu->adrcode & MA_MAP5) mtex= wo->mtex[4]; - else if (icu->adrcode & MA_MAP6) mtex= wo->mtex[5]; - else if (icu->adrcode & MA_MAP7) mtex= wo->mtex[6]; - else if (icu->adrcode & MA_MAP8) mtex= wo->mtex[7]; - else if (icu->adrcode & MA_MAP9) mtex= wo->mtex[8]; - else if (icu->adrcode & MA_MAP10) mtex= wo->mtex[9]; - else if (icu->adrcode & MA_MAP11) mtex= wo->mtex[10]; - else if (icu->adrcode & MA_MAP12) mtex= wo->mtex[11]; - else if (icu->adrcode & MA_MAP13) mtex= wo->mtex[12]; - else if (icu->adrcode & MA_MAP14) mtex= wo->mtex[13]; - else if (icu->adrcode & MA_MAP15) mtex= wo->mtex[14]; - else if (icu->adrcode & MA_MAP16) mtex= wo->mtex[15]; - else if (icu->adrcode & MA_MAP17) mtex= wo->mtex[16]; - else if (icu->adrcode & MA_MAP18) mtex= wo->mtex[17]; + + /* check constraints for local IPO's */ + for (con= ob->constraints.first; con; con= con->next) { + /* if constraint has own IPO, convert add these to Object + * (NOTE: they're most likely to be drivers too) + */ + if (con->ipo) { + /* Verify if there's AnimData block, just in case */ + BKE_id_add_animdata(id); - if (mtex) - poin= give_mtex_poin(mtex, (icu->adrcode & (MA_MAP1-1))); + /* although this was the constraint's local IPO, we still need to provide con + * so that drivers can be added properly... + */ + ipo_to_animdata(id, con->ipo, NULL, con->name); + con->ipo->id.us--; + con->ipo= NULL; } + + /* check for Action Constraint */ + // XXX do we really want to do this here? } - break; - case ID_LA: /* lamp channels ----------------------------- */ - { - Lamp *la= (Lamp *)id; - - switch (icu->adrcode) { - case LA_ENERGY: - poin= &(la->energy); break; - case LA_COL_R: - poin= &(la->r); break; - case LA_COL_G: - poin= &(la->g); break; - case LA_COL_B: - poin= &(la->b); break; - case LA_DIST: - poin= &(la->dist); break; - case LA_SPOTSI: - poin= &(la->spotsize); break; - case LA_SPOTBL: - poin= &(la->spotblend); break; - case LA_QUAD1: - poin= &(la->att1); break; - case LA_QUAD2: - poin= &(la->att2); break; - case LA_HALOINT: - poin= &(la->haint); break; - } + + /* check constraint channels - we need to remove them anyway... */ + if (ob->constraintChannels.first) { + /* Verify if there's AnimData block */ + BKE_id_add_animdata(id); - if (poin == NULL) { - if (icu->adrcode & MA_MAP1) mtex= la->mtex[0]; - else if (icu->adrcode & MA_MAP2) mtex= la->mtex[1]; - else if (icu->adrcode & MA_MAP3) mtex= la->mtex[2]; - else if (icu->adrcode & MA_MAP4) mtex= la->mtex[3]; - else if (icu->adrcode & MA_MAP5) mtex= la->mtex[4]; - else if (icu->adrcode & MA_MAP6) mtex= la->mtex[5]; - else if (icu->adrcode & MA_MAP7) mtex= la->mtex[6]; - else if (icu->adrcode & MA_MAP8) mtex= la->mtex[7]; - else if (icu->adrcode & MA_MAP9) mtex= la->mtex[8]; - else if (icu->adrcode & MA_MAP10) mtex= la->mtex[9]; - else if (icu->adrcode & MA_MAP11) mtex= la->mtex[10]; - else if (icu->adrcode & MA_MAP12) mtex= la->mtex[11]; - else if (icu->adrcode & MA_MAP13) mtex= la->mtex[12]; - else if (icu->adrcode & MA_MAP14) mtex= la->mtex[13]; - else if (icu->adrcode & MA_MAP15) mtex= la->mtex[14]; - else if (icu->adrcode & MA_MAP16) mtex= la->mtex[15]; - else if (icu->adrcode & MA_MAP17) mtex= la->mtex[16]; - else if (icu->adrcode & MA_MAP18) mtex= la->mtex[17]; - - if (mtex) - poin= give_mtex_poin(mtex, (icu->adrcode & (MA_MAP1-1))); - } - } - break; - case ID_CA: /* camera channels ----------------------------- */ - { - Camera *ca= (Camera *)id; - - switch (icu->adrcode) { - case CAM_LENS: - if (ca->type == CAM_ORTHO) - poin= &(ca->ortho_scale); - else - poin= &(ca->lens); - break; - case CAM_STA: - poin= &(ca->clipsta); break; - case CAM_END: - poin= &(ca->clipend); break; - - case CAM_YF_APERT: - poin= &(ca->YF_aperture); break; - case CAM_YF_FDIST: - poin= &(ca->YF_dofdist); break; + for (conchan= ob->constraintChannels.first; conchan; conchan= conchann) { + /* get pointer to next Constraint Channel */ + conchann= conchan->next; - case CAM_SHIFT_X: - poin= &(ca->shiftx); break; - case CAM_SHIFT_Y: - poin= &(ca->shifty); break; - } - } - break; - case ID_SO: /* sound channels ----------------------------- */ - { - bSound *snd= (bSound *)id; - - switch (icu->adrcode) { - case SND_VOLUME: - poin= &(snd->volume); break; - case SND_PITCH: - poin= &(snd->pitch); break; - case SND_PANNING: - poin= &(snd->panning); break; - case SND_ATTEN: - poin= &(snd->attenuation); break; - } - } - break; - case ID_PA: /* particle channels ----------------------------- */ - { - ParticleSettings *part= (ParticleSettings *)id; - - switch (icu->adrcode) { - case PART_EMIT_FREQ: - case PART_EMIT_LIFE: - case PART_EMIT_VEL: - case PART_EMIT_AVE: - case PART_EMIT_SIZE: - poin= NULL; - break; - - case PART_CLUMP: - poin= &(part->clumpfac); break; - case PART_AVE: - poin= &(part->avefac); break; - case PART_SIZE: - poin= &(part->size); break; - case PART_DRAG: - poin= &(part->dragfac); break; - case PART_BROWN: - poin= &(part->brownfac); break; - case PART_DAMP: - poin= &(part->dampfac); break; - case PART_LENGTH: - poin= &(part->length); break; - case PART_GRAV_X: - poin= &(part->acc[0]); break; - case PART_GRAV_Y: - poin= &(part->acc[1]); break; - case PART_GRAV_Z: - poin= &(part->acc[2]); break; - case PART_KINK_AMP: - poin= &(part->kink_amp); break; - case PART_KINK_FREQ: - poin= &(part->kink_freq); break; - case PART_KINK_SHAPE: - poin= &(part->kink_shape); break; - case PART_BB_TILT: - poin= &(part->bb_tilt); break; + /* convert Constraint Channel's IPO data */ + if (conchan->ipo) { + ipo_to_animdata(id, conchan->ipo, NULL, conchan->name); + conchan->ipo->id.us--; + conchan->ipo= NULL; + } - case PART_PD_FSTR: - if (part->pd) poin= &(part->pd->f_strength); - break; - case PART_PD_FFALL: - if (part->pd) poin= &(part->pd->f_power); - break; - case PART_PD_FMAXD: - if (part->pd) poin= &(part->pd->maxdist); - break; - case PART_PD2_FSTR: - if (part->pd2) poin= &(part->pd2->f_strength); - break; - case PART_PD2_FFALL: - if (part->pd2) poin= &(part->pd2->f_power); - break; - case PART_PD2_FMAXD: - if (part->pd2) poin= &(part->pd2->maxdist); - break; + /* free Constraint Channel */ + BLI_freelinkN(&ob->constraintChannels, conchan); } } - break; } - - /* return pointer */ - return poin; -} - -/* --------------------- IPO-Curve Limits ----------------------------- */ - -/* set limits for IPO-curve - * Note: must be synced with UI and PyAPI - */ -void set_icu_vars (IpoCurve *icu) -{ - /* defaults. 0.0 for y-extents makes these ignored */ - icu->ymin= icu->ymax= 0.0; - icu->ipo= IPO_BEZ; - switch (icu->blocktype) { - case ID_OB: /* object channels ----------------------------- */ - { - if (icu->adrcode == OB_LAY) { - icu->ipo= IPO_CONST; - icu->vartype= IPO_BITS; - } - } - break; - case ID_MA: /* material channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case MA_HASIZE: - icu->ymax= 10000.0; break; - case MA_HARD: - icu->ymax= 511.0; break; - case MA_SPEC: - icu->ymax= 2.0; break; - case MA_MODE: - icu->ipo= IPO_CONST; - icu->vartype= IPO_BITS; break; - case MA_RAYM: - icu->ymax= 1.0; break; - case MA_TRANSLU: - icu->ymax= 1.0; break; - case MA_IOR: - icu->ymin= 1.0; - icu->ymax= 3.0; break; - case MA_FRESMIR: - icu->ymax= 5.0; break; - case MA_FRESMIRI: - icu->ymin= 1.0; - icu->ymax= 5.0; break; - case MA_FRESTRA: - icu->ymax= 5.0; break; - case MA_FRESTRAI: - icu->ymin= 1.0; - icu->ymax= 5.0; break; - case MA_ADD: - icu->ymax= 1.0; break; - case MA_EMIT: - icu->ymax= 2.0; break; - default: - icu->ymax= 1.0; break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 1000.0; - icu->ymin= -1000.0; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0; - break; - case MAP_NORF: - icu->ymax= 25.0; - break; - } - } - } - break; - case ID_TE: /* texture channels ----------------------------- */ - { - switch (icu->adrcode & (MA_MAP1-1)) { - case TE_NSIZE: - icu->ymin= 0.0001f; - icu->ymax= 2.0f; - break; - case TE_NDEPTH: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_NTYPE: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 1.0f; - break; - case TE_TURB: - icu->ymax= 200.0f; - break; - case TE_VNW1: - case TE_VNW2: - case TE_VNW3: - case TE_VNW4: - icu->ymax= 2.0f; - icu->ymin= -2.0f; - break; - case TE_VNMEXP: - icu->ymax= 10.0f; - icu->ymin= 0.01f; - break; - case TE_VN_DISTM: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_VN_COLT: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 3.0f; - break; - case TE_ISCA: - icu->ymax= 10.0f; - icu->ymin= 0.01f; - break; - case TE_DISTA: - icu->ymax= 10.0f; - break; - case TE_MG_TYP: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_MGH: - icu->ymin= 0.0001f; - icu->ymax= 2.0f; - break; - case TE_MG_LAC: - case TE_MG_OFF: - case TE_MG_GAIN: - icu->ymax= 6.0f; break; - case TE_MG_OCT: - icu->ymax= 8.0f; break; - case TE_N_BAS1: - case TE_N_BAS2: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 8.0f; - break; - case TE_COL_R: - icu->ymax= 0.0f; break; - case TE_COL_G: - icu->ymax= 2.0f; break; - case TE_COL_B: - icu->ymax= 2.0f; break; - case TE_BRIGHT: - icu->ymax= 2.0f; break; - case TE_CONTRA: - icu->ymax= 5.0f; break; - } - } - break; - case ID_SEQ: /* sequence channels ----------------------------- */ - { - icu->ymax= 1.0f; - } - break; - case ID_CU: /* curve channels ----------------------------- */ - { - icu->ymax= 1.0f; - } - break; - case ID_WO: /* world channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case WO_EXPOS: - icu->ymax= 5.0f; break; - - case WO_MISTDI: - case WO_MISTSTA: - case WO_MISTHI: - case WO_STARDIST: - case WO_STARSIZE: - break; - - default: - icu->ymax= 1.0f; - break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 100.0f; - icu->ymin= -100.0f; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_NORF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0f; - } - } - } - break; - case ID_LA: /* lamp channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case LA_ENERGY: - case LA_DIST: - break; - - case LA_COL_R: - case LA_COL_G: - case LA_COL_B: - case LA_SPOTBL: - case LA_QUAD1: - case LA_QUAD2: - icu->ymax= 1.0f; break; - - case LA_SPOTSI: - icu->ymax= 180.0f; break; - - case LA_HALOINT: - icu->ymax= 5.0f; break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 100.0f; - icu->ymin= -100.0f; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_NORF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0f; - } - } - } - break; - case ID_CA: /* camera channels ----------------------------- */ - { - switch (icu->adrcode) { - case CAM_LENS: - icu->ymin= 1.0f; - icu->ymax= 1000.0f; - break; - case CAM_STA: - icu->ymin= 0.001f; - break; - case CAM_END: - icu->ymin= 0.1f; - break; - - case CAM_YF_APERT: - icu->ymin = 0.0f; - icu->ymax = 2.0f; - break; - case CAM_YF_FDIST: - icu->ymin = 0.0f; - icu->ymax = 5000.0f; - break; - - case CAM_SHIFT_X: - case CAM_SHIFT_Y: - icu->ymin= -2.0f; - icu->ymax= 2.0f; - break; - } + /* shapekeys */ + for (id= main->key.first; id; id= id->next) { + Key *key= (Key *)id; + + if (G.f & G_DEBUG) printf("\tconverting key %s \n", id->name+2); + + /* we're only interested in the IPO + * NOTE: for later, it might be good to port these over to Object instead, as many of these + * are likely to be drivers, but it's hard to trace that from here, so move this to Ob loop? + */ + if (key->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Shapekey data... */ + ipo_to_animdata(id, key->ipo, NULL, NULL); + key->ipo->id.us--; + key->ipo= NULL; } - break; - case ID_SO: /* sound channels ----------------------------- */ - { - switch (icu->adrcode) { - case SND_VOLUME: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case SND_PITCH: - icu->ymin= -12.0f; - icu->ymin= 12.0f; - break; - case SND_PANNING: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case SND_ATTEN: - icu->ymin= 0.0f; - icu->ymin= 1.0f; - break; - } + } + + /* materials */ + for (id= main->mat.first; id; id= id->next) { + Material *ma= (Material *)id; + + if (G.f & G_DEBUG) printf("\tconverting material %s \n", id->name+2); + + /* we're only interested in the IPO */ + if (ma->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Material data... */ + ipo_to_animdata(id, ma->ipo, NULL, NULL); + ma->ipo->id.us--; + ma->ipo= NULL; } - break; - case ID_PA: /* particle channels ----------------------------- */ - { - switch (icu->adrcode) { - case PART_EMIT_LIFE: - case PART_SIZE: - case PART_KINK_FREQ: - case PART_EMIT_VEL: - case PART_EMIT_AVE: - case PART_EMIT_SIZE: - icu->ymin= 0.0f; - break; - case PART_CLUMP: - icu->ymin= -1.0f; - icu->ymax= 1.0f; - break; - case PART_DRAG: - case PART_DAMP: - case PART_LENGTH: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case PART_KINK_SHAPE: - icu->ymin= -0.999f; - icu->ymax= 0.999f; - break; - } + } + + /* textures */ + for (id= main->tex.first; id; id= id->next) { + Tex *te= (Tex *)id; + + if (G.f & G_DEBUG) printf("\tconverting texture %s \n", id->name+2); + + /* we're only interested in the IPO */ + if (te->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Texture data... */ + ipo_to_animdata(id, te->ipo, NULL, NULL); + te->ipo->id.us--; + te->ipo= NULL; } - break; - case ID_CO: /* constraint channels ----------------------------- */ - { - icu->ymin= 0.0f; - icu->ymax= 1.0f; + } + + /* cameras */ + for (id= main->camera.first; id; id= id->next) { + Camera *ca= (Camera *)id; + + if (G.f & G_DEBUG) printf("\tconverting camera %s \n", id->name+2); + + /* we're only interested in the IPO */ + if (ca->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Camera data... */ + ipo_to_animdata(id, ca->ipo, NULL, NULL); + ca->ipo->id.us--; + ca->ipo= NULL; } - break; } - /* by default, slider limits will be icu->ymin and icu->ymax */ - icu->slide_min= icu->ymin; - icu->slide_max= icu->ymax; -} - -/* --------------------- Pointer I/O API ----------------------------- */ - -/* write the given value directly into the given pointer */ -void write_ipo_poin (void *poin, int type, float val) -{ - /* Note: we only support a limited number of types, with the value - * to set needing to be cast to the appropriate type first - * -> (float to integer conversions could be slow) - */ - switch(type) { - case IPO_FLOAT: - *((float *)poin)= val; - break; - - case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */ - *((float *)poin)= (float)(val * M_PI_2 / 9.0); - break; - - case IPO_INT: - case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil! - case IPO_LONG: - *((int *)poin)= (int)val; - break; - - case IPO_SHORT: - case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil! - *((short *)poin)= (short)val; - break; - - case IPO_CHAR: - case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil! - *((char *)poin)= (char)val; - break; + /* lamps */ + for (id= main->lamp.first; id; id= id->next) { + Lamp *la= (Lamp *)id; + + if (G.f & G_DEBUG) printf("\tconverting lamp %s \n", id->name+2); + + /* we're only interested in the IPO */ + if (la->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Lamp data... */ + ipo_to_animdata(id, la->ipo, NULL, NULL); + la->ipo->id.us--; + la->ipo= NULL; + } } -} - -/* read the value from the pointer that was obtained */ -float read_ipo_poin (void *poin, int type) -{ - float val = 0.0; - /* Note: we only support a limited number of types, with the value - * to set needing to be cast to the appropriate type first - * -> (int to float conversions may loose accuracy in rare cases) + /* --------- Unconverted Animation Data ------------------ */ + /* For Animation data which may not be directly connected (i.e. not linked) to any other + * data, we need to perform a separate pass to make sure that they are converted to standalone + * Actions which may then be able to be reused. This does mean that we will be going over data that's + * already been converted, but there are no problems with that. + * + * The most common case for this will be Action Constraints, or IPO's with Fake-Users. + * We collect all drivers that were found into a temporary collection, and free them in one go, as they're + * impossible to resolve. */ - switch (type) { - case IPO_FLOAT: - val= *((float *)poin); - break; - - case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */ - val= *( (float *)poin); - val = (float)(val / (M_PI_2/9.0)); - break; - - case IPO_INT: - case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil! - case IPO_LONG: - val= (float)( *((int *)poin) ); - break; - - case IPO_SHORT: - case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil! - val= *((short *)poin); - break; - - case IPO_CHAR: - case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil - val= *((char *)poin); - break; - } - /* return value */ - return val; -} - -// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!! - - -/* ***************************** IPO <--> GameEngine Interface ********************************* */ - -/* channels is max 32 items, allocated by calling function */ -short IPO_GetChannels (Ipo *ipo, IPO_Channel *channels) -{ - IpoCurve *icu; - int total = 0; + /* actions */ + for (id= main->action.first; id; id= id->next) { + bAction *act= (bAction *)id; + + if (G.f & G_DEBUG) printf("\tconverting action %s \n", id->name+2); + + /* be careful! some of the actions we encounter will be converted ones... */ + action_to_animato(act, &act->groups, &act->curves, &drivers); + } - /* don't do anything with no IPO-block */ - if (ipo == NULL) - return 0; + /* ipo's */ + for (id= main->ipo.first; id; id= id->next) { + Ipo *ipo= (Ipo *)id; + + if (G.f & G_DEBUG) printf("\tconverting ipo %s \n", id->name+2); + + /* most likely this IPO has already been processed, so check if any curves left to convert */ + if (ipo->curve.first) { + bAction *new_act; + + /* add a new action for this, and convert all data into that action */ + new_act= add_empty_action("ConvIPO_Action"); // XXX need a better name... + ipo_to_animato(ipo, NULL, NULL, NULL, &new_act->curves, &drivers); + } + + /* clear fake-users, and set user-count to zero to make sure it is cleared on file-save */ + ipo->id.us= 0; + ipo->id.flag &= ~LIB_FAKEUSER; + } - /* store the IPO-curve's adrcode in the relevant channel slot */ - for (icu=ipo->curve.first; (icu) && (total < 31); icu=icu->next, total++) - channels[total]= icu->adrcode; + /* free unused drivers from actions + ipos */ + free_fcurves(&drivers); - /* return the number of channels stored */ - return total; + printf("INFO: Animato convert done \n"); // xxx debug } -/* Get the float value for channel 'channel' at time 'ctime' */ -float IPO_GetFloatValue (Ipo *ipo, IPO_Channel channel, float ctime) -{ - /* don't evaluate if no IPO to use */ - if (ipo == NULL) - return 0; - - /* only calculate the specified channel */ - calc_ipo_spec(ipo, channel, &ctime); - - /* unapply rotation hack, as gameengine doesn't use it */ - if ((OB_ROT_X <= channel) && (channel <= OB_DROT_Z)) - ctime *= (float)(M_PI_2/9.0); - - /* return the value of this channel */ - return ctime; -} diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 755a41ec4b2..595ba37e09c 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -35,8 +35,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" -#include "DNA_ipo_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -44,12 +44,11 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "BKE_animsys.h" #include "BKE_action.h" -#include "BKE_bad_level_calls.h" #include "BKE_blender.h" #include "BKE_curve.h" #include "BKE_global.h" -#include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -60,7 +59,6 @@ #include "BLI_blenlib.h" -#include "blendef.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -69,6 +67,11 @@ #define KEY_BPOINT 1 #define KEY_BEZTRIPLE 2 + // old defines from DNA_ipo_types.h for data-type +#define IPO_FLOAT 4 +#define IPO_BEZTRIPLE 100 +#define IPO_BPOINT 101 + int slurph_opt= 1; @@ -76,8 +79,7 @@ void free_key(Key *key) { KeyBlock *kb; - if(key->ipo) key->ipo->id.us--; - + BKE_free_animdata((ID *)key); while( (kb= key->block.first) ) { @@ -112,6 +114,7 @@ Key *add_key(ID *id) /* common function */ key->type= KEY_NORMAL; key->from= id; + // XXX the code here uses some defines which will soon be depreceated... if( GS(id->name)==ID_ME) { el= key->elemstr; @@ -152,9 +155,11 @@ Key *copy_key(Key *key) keyn= copy_libblock(key); +#if 0 // XXX old animation system keyn->ipo= copy_ipo(key->ipo); - - duplicatelist(&keyn->block, &key->block); +#endif // XXX old animation system + + BLI_duplicatelist(&keyn->block, &key->block); kb= key->block.first; kbn= keyn->block.first; @@ -181,11 +186,13 @@ void make_local_key(Key *key) key->id.lib= 0; new_id(0, (ID *)key, 0); + +#if 0 // XXX old animation system make_local_ipo(key->ipo); +#endif // XXX old animation system } -/* - * Sort shape keys and Ipo curves after a change. This assumes that at most +/* Sort shape keys and Ipo curves after a change. This assumes that at most * one key was moved, which is a valid assumption for the places it's * currently being called. */ @@ -193,30 +200,30 @@ void make_local_key(Key *key) void sort_keys(Key *key) { KeyBlock *kb; - short i, adrcode; - IpoCurve *icu = NULL; + //short i, adrcode; + //IpoCurve *icu = NULL; KeyBlock *kb2; /* locate the key which is out of position */ - for( kb= key->block.first; kb; kb= kb->next ) - if( kb->next && kb->pos > kb->next->pos ) + for (kb= key->block.first; kb; kb= kb->next) + if ((kb->next) && (kb->pos > kb->next->pos)) break; /* if we find a key, move it */ - if( kb ) { + if (kb) { kb = kb->next; /* next key is the out-of-order one */ BLI_remlink(&key->block, kb); - + /* find the right location and insert before */ - for( kb2=key->block.first; kb2; kb2= kb2->next ) { - if( kb2->pos > kb->pos ) { + for (kb2=key->block.first; kb2; kb2= kb2->next) { + if (kb2->pos > kb->pos) { BLI_insertlink(&key->block, kb2->prev, kb); break; } } - + /* if more than one Ipo curve, see if this key had a curve */ - +#if 0 // XXX old animation system if(key->ipo && key->ipo->curve.first != key->ipo->curve.last ) { for(icu= key->ipo->curve.first; icu; icu= icu->next) { /* if we find the curve, remove it and reinsert in the @@ -234,13 +241,13 @@ void sort_keys(Key *key) } } } - + /* kb points at the moved key, icu at the moved ipo (if it exists). * go back now and renumber adrcodes */ /* first new code */ adrcode = kb2->adrcode; - for( i = kb->adrcode - adrcode; i >= 0; --i, ++adrcode ) { + for (i = kb->adrcode - adrcode; i >= 0; i--, adrcode++) { /* if the next ipo curve matches the current key, renumber it */ if(icu && icu->adrcode == kb->adrcode ) { icu->adrcode = adrcode; @@ -250,6 +257,7 @@ void sort_keys(Key *key) kb->adrcode = adrcode; kb = kb->next; } +#endif // XXX old animation system } /* new rule; first key is refkey, this to match drawing channels... */ @@ -638,6 +646,8 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode if(key->from==NULL) return; + if (G.f & G_DEBUG) printf("do_rel_key() \n"); + if( GS(key->from->name)==ID_ME ) { ofs[0]= sizeof(MVert); ofs[1]= 0; @@ -673,11 +683,15 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode if(kb!=key->refkey) { float icuval= kb->curval; + if (G.f & G_DEBUG) printf("\tdo rel key %s : %s = %f \n", key->id.name+2, kb->name, icuval); + /* only with value, and no difference allowed */ if(!(kb->flag & KEYBLOCK_MUTE) && icuval!=0.0f && kb->totelem==tot) { KeyBlock *refb; float weight, *weights= kb->weights; + if (G.f & G_DEBUG) printf("\t\tnot skipped \n"); + poin= basispoin; from= kb->data; /* reference now can be any block */ @@ -748,6 +762,8 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock * if(key->from==0) return; + if (G.f & G_DEBUG) printf("do_key() \n"); + if( GS(key->from->name)==ID_ME ) { ofs[0]= sizeof(MVert); ofs[1]= 0; @@ -995,7 +1011,7 @@ static float *get_weights_array(Object *ob, char *vgroup) return NULL; } -static int do_mesh_key(Object *ob, Mesh *me) +static int do_mesh_key(Scene *scene, Object *ob, Mesh *me) { KeyBlock *k[4]; float cfra, ctime, t[4], delta, loc[3], size[3]; @@ -1008,7 +1024,11 @@ static int do_mesh_key(Object *ob, Mesh *me) /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */ me->key->from= (ID *)me; + if (G.f & G_DEBUG) printf("do mesh key ob:%s me:%s ke:%s \n", ob->id.name+2, me->id.name+2, me->key->id.name+2); + if(me->key->slurph && me->key->type!=KEY_RELATIVE ) { + if (G.f & G_DEBUG) printf("\tslurph key\n"); + delta= me->key->slurph; delta/= me->totvert; @@ -1019,15 +1039,20 @@ static int do_mesh_key(Object *ob, Mesh *me) /* in do_key and cp_key the case a>tot is handled */ } - cfra= G.scene->r.cfra; + cfra= (float)scene->r.cfra; for(a=0; a<me->totvert; a+=step, cfra+= delta) { - ctime= bsystem_time(0, cfra, 0.0); + ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx ugly cruft! +#if 0 // XXX old animation system if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system + // XXX for now... since speed curve cannot be directly ported yet + ctime /= 100.0f; + CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing flag= setkeys(ctime, &me->key->block, k, t, 0); if(flag==0) { @@ -1043,10 +1068,11 @@ static int do_mesh_key(Object *ob, Mesh *me) else boundbox_mesh(me, loc, size); } else { - if(me->key->type==KEY_RELATIVE) { KeyBlock *kb; + if (G.f & G_DEBUG) printf("\tdo relative \n"); + for(kb= me->key->block.first; kb; kb= kb->next) kb->weights= get_weights_array(ob, kb->vgroup); @@ -1058,13 +1084,20 @@ static int do_mesh_key(Object *ob, Mesh *me) } } else { - ctime= bsystem_time(ob, G.scene->r.cfra, 0.0); - + if (G.f & G_DEBUG) printf("\tdo absolute \n"); + + ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); // xxx old cruft + +#if 0 // XXX old animation system if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } - +#endif // XXX old animation system + // XXX for now... since speed curve cannot be directly ported yet + ctime /= 100.0f; + CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing + flag= setkeys(ctime, &me->key->block, k, t, 0); if(flag==0) { do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0); @@ -1151,7 +1184,7 @@ static void do_rel_cu_key(Curve *cu, float ctime) } } -static int do_curve_key(Curve *cu) +static int do_curve_key(Scene *scene, Curve *cu) { KeyBlock *k[4]; float cfra, ctime, t[4], delta; @@ -1174,15 +1207,16 @@ static int do_curve_key(Curve *cu) /* in do_key and cp_key the case a>tot has been handled */ } - cfra= G.scene->r.cfra; + cfra= (float)scene->r.cfra; for(a=0; a<tot; a+=step, cfra+= delta) { - - ctime= bsystem_time(0, cfra, 0.0); + ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft +#if 0 // XXX old animation system if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system flag= setkeys(ctime, &cu->key->block, k, t, 0); if(flag==0) { @@ -1200,16 +1234,18 @@ static int do_curve_key(Curve *cu) } else { - ctime= bsystem_time(NULL, (float)G.scene->r.cfra, 0.0); + ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0); if(cu->key->type==KEY_RELATIVE) { do_rel_cu_key(cu, ctime); } else { +#if 0 // XXX old animation system if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system flag= setkeys(ctime, &cu->key->block, k, t, 0); @@ -1223,7 +1259,7 @@ static int do_curve_key(Curve *cu) return 1; } -static int do_latt_key(Object *ob, Lattice *lt) +static int do_latt_key(Scene *scene, Object *ob, Lattice *lt) { KeyBlock *k[4]; float delta, cfra, ctime, t[4]; @@ -1238,15 +1274,17 @@ static int do_latt_key(Object *ob, Lattice *lt) delta= lt->key->slurph; delta/= (float)tot; - cfra= G.scene->r.cfra; + cfra= (float)scene->r.cfra; for(a=0; a<tot; a++, cfra+= delta) { - ctime= bsystem_time(0, cfra, 0.0); + ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft +#if 0 // XXX old animation system if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system flag= setkeys(ctime, <->key->block, k, t, 0); if(flag==0) { @@ -1259,7 +1297,7 @@ static int do_latt_key(Object *ob, Lattice *lt) } } else { - ctime= bsystem_time(NULL, (float)G.scene->r.cfra, 0.0); + ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0); if(lt->key->type==KEY_RELATIVE) { KeyBlock *kb; @@ -1275,10 +1313,12 @@ static int do_latt_key(Object *ob, Lattice *lt) } } else { +#if 0 // XXX old animation system if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) { ctime /= 100.0; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system flag= setkeys(ctime, <->key->block, k, t, 0); if(flag==0) { @@ -1296,7 +1336,7 @@ static int do_latt_key(Object *ob, Lattice *lt) } /* returns 1 when key applied */ -int do_ob_key(Object *ob) +int do_ob_key(Scene *scene, Object *ob) { Key *key= ob_get_key(ob); @@ -1305,7 +1345,9 @@ int do_ob_key(Object *ob) if(ob->shapeflag & (OB_SHAPE_LOCK|OB_SHAPE_TEMPLOCK)) { KeyBlock *kb= BLI_findlink(&key->block, ob->shapenr-1); - + + if (G.f & G_DEBUG) printf("ob %s, key %s locked \n", ob->id.name+2, key->id.name+2); + if(kb && (kb->flag & KEYBLOCK_MUTE)) kb= key->refkey; @@ -1340,17 +1382,24 @@ int do_ob_key(Object *ob) return 1; } else { +#if 0 // XXX old animation system + // NOTE: this stuff was NEVER reliable at all... if(ob->ipoflag & OB_ACTION_KEY) - do_all_object_actions(ob); + do_all_object_actions(scene, ob); else { - calc_ipo(key->ipo, bsystem_time(ob, G.scene->r.cfra, 0.0)); + calc_ipo(key->ipo, bsystem_time(scene, ob, scene->r.cfra, 0.0)); execute_ipo((ID *)key, key->ipo); } +#endif // XXX old animation system + /* do shapekey local drivers */ + float ctime= (float)scene->r.cfra; // XXX this needs to be checked + if (G.f & G_DEBUG) printf("ob %s - do shapekey (%s) drivers \n", ob->id.name+2, key->id.name+2); + BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS); - if(ob->type==OB_MESH) return do_mesh_key(ob, ob->data); - else if(ob->type==OB_CURVE) return do_curve_key( ob->data); - else if(ob->type==OB_SURF) return do_curve_key( ob->data); - else if(ob->type==OB_LATTICE) return do_latt_key(ob, ob->data); + if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data); + else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data); + else if(ob->type==OB_SURF) return do_curve_key(scene, ob->data); + else if(ob->type==OB_LATTICE) return do_latt_key(scene, ob, ob->data); } return 0; @@ -1407,3 +1456,18 @@ KeyBlock *key_get_keyblock(Key *key, int index) return NULL; } + +/* get the appropriate KeyBlock given a name to search for */ +KeyBlock *key_get_named_keyblock(Key *key, const char name[]) +{ + KeyBlock *kb; + + if (key && name) { + for (kb= key->block.first; kb; kb= kb->next) { + if (strcmp(name, kb->name)==0) + return kb; + } + } + + return NULL; +} diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 6614c657647..5cf52d09314 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -30,6 +30,7 @@ * ***** END GPL LICENSE BLOCK ***** */ + #include <stdio.h> #include <string.h> #include <math.h> @@ -41,7 +42,6 @@ #include "BLI_arithb.h" #include "DNA_armature_types.h" -#include "DNA_ipo_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -59,7 +59,6 @@ #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_global.h" -#include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -70,18 +69,7 @@ #include "BKE_screen.h" #include "BKE_utildefines.h" -#include "BIF_editdeform.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "blendef.h" - -Lattice *editLatt=0; -static Lattice *deformLatt=0; - -static float *latticedata=0, latmat[4][4]; +//XXX #include "BIF_editdeform.h" void calc_lat_fudu(int flag, int res, float *fu, float *du) { @@ -223,7 +211,9 @@ Lattice *copy_lattice(Lattice *lt) ltn= copy_libblock(lt); ltn->def= MEM_dupallocN(lt->def); +#if 0 // XXX old animation system id_us_plus((ID *)ltn->ipo); +#endif // XXX old animation system ltn->key= copy_key(ltn->key); if(ltn->key) ltn->key->from= (ID *)ltn; @@ -241,6 +231,11 @@ void free_lattice(Lattice *lt) { if(lt->def) MEM_freeN(lt->def); if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); + if(lt->editlatt) { + if(lt->def) MEM_freeN(lt->def); + if(lt->dvert) free_dverts(lt->dvert, lt->pntsu*lt->pntsv*lt->pntsw); + MEM_freeN(lt->editlatt); + } } @@ -299,31 +294,34 @@ void make_local_lattice(Lattice *lt) void init_latt_deform(Object *oblatt, Object *ob) { /* we make an array with all differences */ - Lattice *lt = deformLatt = (oblatt==G.obedit)?editLatt:oblatt->data; - BPoint *bp = lt->def; + Lattice *lt= oblatt->data; + BPoint *bp; DispList *dl = find_displist(&oblatt->disp, DL_VERTS); float *co = dl?dl->verts:NULL; float *fp, imat[4][4]; float fu, fv, fw; int u, v, w; - fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata"); + if(lt->editlatt) lt= lt->editlatt; + bp = lt->def; + + fp= lt->latticedata= MEM_mallocN(sizeof(float)*3*lt->pntsu*lt->pntsv*lt->pntsw, "latticedata"); /* for example with a particle system: ob==0 */ - if(ob==0) { + if(ob==NULL) { /* in deformspace, calc matrix */ - Mat4Invert(latmat, oblatt->obmat); + Mat4Invert(lt->latmat, oblatt->obmat); /* back: put in deform array */ - Mat4Invert(imat, latmat); + Mat4Invert(imat, lt->latmat); } else { /* in deformspace, calc matrix */ Mat4Invert(imat, oblatt->obmat); - Mat4MulMat4(latmat, ob->obmat, imat); + Mat4MulMat4(lt->latmat, ob->obmat, imat); /* back: put in deform array */ - Mat4Invert(imat, latmat); + Mat4Invert(imat, lt->latmat); } for(w=0,fw=lt->fw; w<lt->pntsw; w++,fw+=lt->dw) { @@ -345,21 +343,20 @@ void init_latt_deform(Object *oblatt, Object *ob) } } -void calc_latt_deform(float *co, float weight) +void calc_latt_deform(Object *ob, float *co, float weight) { - Lattice *lt; + Lattice *lt= ob->data; float u, v, w, tu[4], tv[4], tw[4]; float *fpw, *fpv, *fpu, vec[3]; int ui, vi, wi, uu, vv, ww; - if(latticedata==0) return; - - lt= deformLatt; /* just for shorter notation! */ + if(lt->editlatt) lt= lt->editlatt; + if(lt->latticedata==NULL) return; /* co is in local coords, treat with latmat */ VECCOPY(vec, co); - Mat4MulVecfl(latmat, vec); + Mat4MulVecfl(lt->latmat, vec); /* u v w coords */ @@ -401,10 +398,10 @@ void calc_latt_deform(float *co, float weight) if(w!=0.0) { if(ww>0) { - if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv; - else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; + if(ww<lt->pntsw) fpw= lt->latticedata + 3*ww*lt->pntsu*lt->pntsv; + else fpw= lt->latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; } - else fpw= latticedata; + else fpw= lt->latticedata; for(vv= vi-1; vv<=vi+2; vv++) { v= w*tv[vv-vi+1]; @@ -437,11 +434,15 @@ void calc_latt_deform(float *co, float weight) } } -void end_latt_deform() +void end_latt_deform(Object *ob) { - - MEM_freeN(latticedata); - latticedata= 0; + Lattice *lt= ob->data; + + if(lt->editlatt) lt= lt->editlatt; + + if(lt->latticedata) + MEM_freeN(lt->latticedata); + lt->latticedata= NULL; } /* calculations is in local space of deformed object @@ -516,7 +517,7 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) /* co: local coord, result local too */ /* returns quaternion for rotation, using cd->no_rot_axis */ /* axis is using another define!!! */ -static int calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd, float *quatp) +static int calc_curve_deform(Scene *scene, Object *par, float *co, short axis, CurveDeform *cd, float *quatp) { Curve *cu= par->data; float fac, loc[4], dir[3], cent[3]; @@ -545,7 +546,7 @@ static int calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd } /* to be sure, mostly after file load */ if(cu->path==NULL) { - makeDispListCurveTypes(par, 0); + makeDispListCurveTypes(scene, par, 0); if(cu->path==NULL) return 0; // happens on append... } @@ -563,13 +564,16 @@ static int calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist); } +#if 0 // XXX old animation system /* we want the ipo to work on the default 100 frame range, because there's no actual time involved in path position */ + // huh? by WHY!!!!???? - Aligorith if(cu->ipo) { fac*= 100.0f; if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0) fac/= 100.0; } +#endif // XXX old animation system if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */ float q[4], mat[3][3], quat[4]; @@ -606,7 +610,7 @@ static int calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd return 0; } -void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup, short defaxis) +void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup, short defaxis) { Curve *cu; int a, flag; @@ -672,7 +676,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v for(j = 0; j < dvert->totweight; j++) { if(dvert->dw[j].def_nr == index) { VECCOPY(vec, vertexCos[a]); - calc_curve_deform(cuOb, vec, defaxis, &cd, NULL); + calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); VecLerpf(vertexCos[a], vertexCos[a], vec, dvert->dw[j].weight); Mat4MulVecfl(cd.objectspace, vertexCos[a]); @@ -690,7 +694,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v } for(a = 0; a < numVerts; a++) { - calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL); + calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); Mat4MulVecfl(cd.objectspace, vertexCos[a]); } } @@ -700,7 +704,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v /* input vec and orco = local coord in armature space */ /* orco is original not-animated or deformed reference point */ /* result written in vec and mat */ -void curve_deform_vector(Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis) +void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis) { CurveDeform cd; float quat[4]; @@ -718,7 +722,7 @@ void curve_deform_vector(Object *cuOb, Object *target, float *orco, float *vec, Mat4MulVecfl(cd.curvespace, vec); - if(calc_curve_deform(cuOb, vec, target->trackflag+1, &cd, quat)) { + if(calc_curve_deform(scene, cuOb, vec, target->trackflag+1, &cd, quat)) { float qmat[3][3]; QuatToMat3(quat, qmat); @@ -773,17 +777,17 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); for(j = 0; j < dvert->totweight; j++) { if (dvert->dw[j].def_nr == index) { - calc_latt_deform(vertexCos[a], dvert->dw[j].weight); + calc_latt_deform(laOb, vertexCos[a], dvert->dw[j].weight); } } } } } else { for(a = 0; a < numVerts; a++) { - calc_latt_deform(vertexCos[a], 1.0f); + calc_latt_deform(laOb, vertexCos[a], 1.0f); } } - end_latt_deform(); + end_latt_deform(laOb); } int object_deform_mball(Object *ob) @@ -870,10 +874,15 @@ void outside_lattice(Lattice *lt) float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3] { - Lattice *lt = (G.obedit==ob)?editLatt:ob->data; - int i, numVerts = *numVerts_r = lt->pntsu*lt->pntsv*lt->pntsw; - float (*vertexCos)[3] = MEM_mallocN(sizeof(*vertexCos)*numVerts,"lt_vcos"); + Lattice *lt = ob->data; + int i, numVerts; + float (*vertexCos)[3]; + if(lt->editlatt) lt= lt->editlatt; + numVerts = *numVerts_r = lt->pntsu*lt->pntsv*lt->pntsw; + + vertexCos = MEM_mallocN(sizeof(*vertexCos)*numVerts,"lt_vcos"); + for (i=0; i<numVerts; i++) { VECCOPY(vertexCos[i], lt->def[i].vec); } @@ -891,28 +900,31 @@ void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3]) } } -void lattice_calc_modifiers(Object *ob) +void lattice_calc_modifiers(Scene *scene, Object *ob) { - float (*vertexCos)[3] = NULL; + Lattice *lt= ob->data; ModifierData *md = modifiers_getVirtualModifierList(ob); - int numVerts, editmode = G.obedit==ob; + float (*vertexCos)[3] = NULL; + int numVerts, editmode = (lt->editlatt!=NULL); freedisplist(&ob->disp); if (!editmode) { - do_ob_key(ob); + do_ob_key(scene, ob); } for (; md; md=md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + md->scene= scene; + if (!(md->mode&eModifierMode_Realtime)) continue; if (editmode && !(md->mode&eModifierMode_Editmode)) continue; if (mti->isDisabled && mti->isDisabled(md)) continue; if (mti->type!=eModifierTypeType_OnlyDeform) continue; if (!vertexCos) vertexCos = lattice_getVertexCos(ob, &numVerts); - mti->deformVerts(md, ob, NULL, vertexCos, numVerts); + mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0); } /* always displist to make this work like derivedmesh */ @@ -933,7 +945,8 @@ struct MDeformVert* lattice_get_deform_verts(struct Object *oblatt) { if(oblatt->type == OB_LATTICE) { - Lattice *lt = (oblatt==G.obedit)?editLatt:(Lattice*)oblatt->data; + Lattice *lt = (Lattice*)oblatt->data; + if(lt->editlatt) lt= lt->editlatt; return lt->dvert; } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 33c1a4da4c7..90ab4e05d44 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -76,12 +76,16 @@ #include "DNA_effect_types.h" #include "DNA_brush_types.h" #include "DNA_particle_types.h" -#include "BKE_particle.h" +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" -#include "BKE_bad_level_calls.h" +#include "BKE_animsys.h" +#include "BKE_context.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_global.h" @@ -110,8 +114,8 @@ #include "BKE_effect.h" #include "BKE_brush.h" #include "BKE_idprop.h" - -#include "DNA_space_types.h" +#include "BKE_particle.h" +#include "BKE_gpencil.h" #define MAX_IDPUP 60 /* was 24 */ @@ -138,6 +142,12 @@ void id_us_plus(ID *id) } } +void id_us_min(ID *id) +{ + if(id) + id->us--; +} + ListBase *wich_libbase(Main *mainlib, short type) { switch( type ) { @@ -195,6 +205,10 @@ ListBase *wich_libbase(Main *mainlib, short type) return &(mainlib->brush); case ID_PA: return &(mainlib->particle); + case ID_WM: + return &(mainlib->wm); + case ID_GD: + return &(mainlib->gpencil); } return 0; } @@ -229,6 +243,7 @@ int set_listbasepointers(Main *main, ListBase **lb) /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */ lb[a++]= &(main->ipo); + lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith) lb[a++]= &(main->key); lb[a++]= &(main->nodetree); lb[a++]= &(main->image); @@ -241,7 +256,6 @@ int set_listbasepointers(Main *main, ListBase **lb) */ lb[a++]= &(main->armature); - lb[a++]= &(main->action); lb[a++]= &(main->mesh); lb[a++]= &(main->curve); @@ -264,6 +278,8 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[a++]= &(main->object); lb[a++]= &(main->scene); lb[a++]= &(main->library); + lb[a++]= &(main->wm); + lb[a++]= &(main->gpencil); lb[a]= NULL; @@ -343,7 +359,7 @@ static ID *alloc_libblock_notest(short type) id= MEM_callocN(sizeof(Text), "text"); break; case ID_SCRIPT: - id= MEM_callocN(sizeof(Script), "script"); + //XXX id= MEM_callocN(sizeof(Script), "script"); break; case ID_SO: id= MEM_callocN(sizeof(bSound), "sound"); @@ -366,6 +382,12 @@ static ID *alloc_libblock_notest(short type) case ID_PA: id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings"); break; + case ID_WM: + id = MEM_callocN(sizeof(wmWindowManager), "Window manager"); + break; + case ID_GD: + id = MEM_callocN(sizeof(bGPdata), "Grease Pencil"); + break; } return id; } @@ -394,6 +416,45 @@ void *alloc_libblock(ListBase *lb, short type, const char *name) /* from blendef: */ #define GS(a) (*((short *)(a))) +/* by spec, animdata is first item after ID */ +/* we still read ->adt itself, to ensure compiler warns when it doesnt exist */ +static void id_copy_animdata(ID *id) +{ + switch(GS(id->name)) { + case ID_OB: + ((Object *)id)->adt= BKE_copy_animdata(((Object *)id)->adt); + break; + case ID_CU: + ((Curve *)id)->adt= BKE_copy_animdata(((Curve *)id)->adt); + break; + case ID_CA: + ((Camera *)id)->adt= BKE_copy_animdata(((Camera *)id)->adt); + break; + case ID_KE: + ((Key *)id)->adt= BKE_copy_animdata(((Key *)id)->adt); + break; + case ID_LA: + ((Lamp *)id)->adt= BKE_copy_animdata(((Lamp *)id)->adt); + break; + case ID_MA: + ((Material *)id)->adt= BKE_copy_animdata(((Material *)id)->adt); + break; + case ID_NT: + ((bNodeTree *)id)->adt= BKE_copy_animdata(((bNodeTree *)id)->adt); + break; + case ID_SCE: + ((Scene *)id)->adt= BKE_copy_animdata(((Scene *)id)->adt); + break; + case ID_TE: + ((Tex *)id)->adt= BKE_copy_animdata(((Tex *)id)->adt); + break; + case ID_WO: + ((World *)id)->adt= BKE_copy_animdata(((World *)id)->adt); + break; + } + +} + /* used everywhere in blenkernel and text.c */ void *copy_libblock(void *rt) { @@ -422,6 +483,8 @@ void *copy_libblock(void *rt) idn->flag |= LIB_NEW; if (id->properties) idn->properties = IDP_CopyProperty(id->properties); + id_copy_animdata(id); + return idn; } @@ -430,6 +493,13 @@ static void free_library(Library *lib) /* no freeing needed for libraries yet */ } +static void (*free_windowmanager_cb)(bContext *, wmWindowManager *)= NULL; + +void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) ) +{ + free_windowmanager_cb= func; +} + /* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */ void free_libblock(ListBase *lb, void *idv) { @@ -494,7 +564,7 @@ void free_libblock(ListBase *lb, void *idv) free_text((Text *)id); break; case ID_SCRIPT: - free_script((Script *)id); + //XXX free_script((Script *)id); break; case ID_SO: sound_free_sound((bSound *)id); @@ -517,6 +587,13 @@ void free_libblock(ListBase *lb, void *idv) case ID_PA: psys_free_settings((ParticleSettings *)id); break; + case ID_WM: + if(free_windowmanager_cb) + free_windowmanager_cb(NULL, (wmWindowManager *)id); + break; + case ID_GD: + free_gpencil_data((bGPdata *)id); + break; } if (id->properties) { @@ -539,7 +616,7 @@ void free_libblock_us(ListBase *lb, void *idv) /* test users */ else printf("ERROR block %s users %d\n", id->name, id->us); } if(id->us==0) { - if( GS(id->name)==ID_OB ) unlink_object((Object *)id); + if( GS(id->name)==ID_OB ) unlink_object(NULL, (Object *)id); free_libblock(lb, id); } @@ -664,52 +741,6 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor } } - /* Silly routine, the only difference between the one - * above is that it only adds items with a matching - * blocktype... this should be unified somehow... - zr - */ -static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype) -{ - ID *id; - int i, nids; - - for (id= lb->first, nids= 0; id; id= id->next) { - Ipo *ipo= (Ipo*) id; - - if (ipo->blocktype==blocktype) - nids++; - } - - if (nids>MAX_IDPUP) { - BLI_dynstr_append(pupds, "DataBrowse %x-2"); - } else { - for (i=0, id= lb->first; id; id= id->next) { - Ipo *ipo= (Ipo*) id; - - if (ipo->blocktype==blocktype) { - char buf[32]; - - if (id==link) - *nr= i+1; - - if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.') - continue; - - get_flags_for_id(id, buf); - - BLI_dynstr_append(pupds, buf); - BLI_dynstr_append(pupds, id->name+2); - sprintf(buf, "%%x%d", i+1); - BLI_dynstr_append(pupds, buf); - - if(id->next) - BLI_dynstr_append(pupds, "|"); - - i++; - } - } - } -} /* used by headerbuttons.c buttons.c editobject.c editseq.c */ /* if nr==NULL no MAX_IDPUP, this for non-header browsing */ @@ -757,28 +788,6 @@ void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb } -/* only used by headerbuttons.c */ -void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype) -{ - DynStr *pupds= BLI_dynstr_new(); - - if (title) { - BLI_dynstr_append(pupds, title); - BLI_dynstr_append(pupds, "%t|"); - } - - if (extraops) { - BLI_dynstr_append(pupds, extraops); - if (BLI_dynstr_get_len(pupds)) - BLI_dynstr_append(pupds, "|"); - } - - IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype); - - *str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); -} - /* used by buttons.c library.c mball.c */ void splitIDname(char *name, char *left, int *nr) { @@ -994,14 +1003,15 @@ static void lib_indirect_test_id(ID *id) if(id->lib) return; - + if(GS(id->name)==ID_OB) { Object *ob= (Object *)id; bActionStrip *strip; Mesh *me; int a; - + + // XXX old animation system! for (strip=ob->nlastrips.first; strip; strip=strip->next){ LIBTAG(strip->object); LIBTAG(strip->act); @@ -1098,6 +1108,27 @@ void test_idbutton(char *name) if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest); } +void text_idbutton(struct ID *id, char *text) +{ + if(id) { + if(GS(id->name)==ID_SCE) + strcpy(text, "SCE: "); + else if(GS(id->name)==ID_SCE) + strcpy(text, "SCR: "); + else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes) + strcpy(text, "NT: "); + else { + text[0]= id->name[0]; + text[1]= id->name[1]; + text[2]= ':'; + text[3]= ' '; + text[4]= 0; + } + } + else + strcpy(text, ""); +} + void rename_id(ID *id, char *name) { ListBase *lb; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 753058b1fdd..b410c521dea 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -47,7 +47,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" -#include "BKE_bad_level_calls.h" +#include "BKE_animsys.h" #include "BKE_blender.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -93,6 +93,8 @@ void free_material(Material *ma) if(ma->ramp_col) MEM_freeN(ma->ramp_col); if(ma->ramp_spec) MEM_freeN(ma->ramp_spec); + BKE_free_animdata((ID *)ma); + BKE_previewimg_free(&ma->preview); BKE_icon_delete((struct ID*)ma); ma->id.icon_id = 0; @@ -194,7 +196,9 @@ Material *copy_material(Material *ma) man= copy_libblock(ma); +#if 0 // XXX old animation system id_us_plus((ID *)man->ipo); +#endif // XXX old animation system id_us_plus((ID *)man->group); @@ -850,21 +854,16 @@ void automatname(Material *ma) } -void delete_material_index() +void delete_material_index(Object *ob) { Material *mao, ***matarar; - Object *ob, *obt; + Object *obt; Curve *cu; Nurb *nu; short *totcolp; int a, actcol; - if(G.obedit) { - error("Unable to perform function in EditMode"); - return; - } - ob= ((G.scene->basact)? (G.scene->basact->object) : 0) ; - if(ob==0 || ob->totcol==0) return; + if(ob==NULL || ob->totcol==0) return; /* take a mesh/curve/mball as starting point, remove 1 index, * AND with all objects that share the ob->data diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 79205814ae7..74d56e81a87 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -50,7 +50,6 @@ #include "BLI_arithb.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" #include "BKE_global.h" #include "BKE_main.h" @@ -120,7 +119,7 @@ MetaBall *copy_mball(MetaBall *mb) mbn= copy_libblock(mb); - duplicatelist(&mbn->elems, &mb->elems); + BLI_duplicatelist(&mbn->elems, &mb->elems); mbn->mat= MEM_dupallocN(mb->mat); for(a=0; a<mbn->totcol; a++) { @@ -286,7 +285,7 @@ int is_basis_mball(Object *ob) * blended. MetaBalls with different basic name can't be * blended. */ -Object *find_basis_mball(Object *basis) +Object *find_basis_mball(Scene *scene, Object *basis) { Base *base; Object *ob,*bob= basis; @@ -297,18 +296,21 @@ Object *find_basis_mball(Object *basis) splitIDname(basis->id.name+2, basisname, &basisnr); totelem= 0; - next_object(0, 0, 0); - while(next_object(1, &base, &ob)) { + /* XXX recursion check, see scene.c, just too simple code this next_object() */ + if(F_ERROR==next_object(scene, 0, 0, 0)) + return NULL; + + while(next_object(scene, 1, &base, &ob)) { if (ob->type==OB_MBALL) { if(ob==bob){ + MetaBall *mb= ob->data; + /* if bob object is in edit mode, then dynamic list of all MetaElems * is stored in editelems */ - if(ob==G.obedit) ml= editelems.first; - /* keep track of linked data too! */ - else if(G.obedit && G.obedit->data==ob->data) ml= editelems.first; + if(mb->editelems) ml= mb->editelems->first; /* if bob object is in object mode */ - else ml= ((MetaBall*)ob->data)->elems.first; + else ml= mb->elems.first; } else{ splitIDname(ob->id.name+2, obname, &obnr); @@ -316,13 +318,13 @@ Object *find_basis_mball(Object *basis) /* object ob has to be in same "group" ... it means, that it has to have * same base of its name */ if(strcmp(obname, basisname)==0){ + MetaBall *mb= ob->data; + /* if object is in edit mode, then dynamic list of all MetaElems * is stored in editelems */ - if(ob==G.obedit) ml= editelems.first; - /* keep track of linked data too! */ - else if(bob==G.obedit && bob->data==ob->data) ml= editelems.first; - /* object is in object mode */ - else ml= ((MetaBall*)ob->data)->elems.first; + if(mb->editelems) ml= mb->editelems->first; + /* if bob object is in object mode */ + else ml= mb->elems.first; if(obnr<basisnr){ if(!(ob->flag & OB_FROMDUPLI)){ @@ -1452,7 +1454,7 @@ void polygonize(PROCESS *mbproc, MetaBall *mb) } } -float init_meta(Object *ob) /* return totsize */ +float init_meta(Scene *scene, Object *ob) /* return totsize */ { Base *base; Object *bob; @@ -1471,8 +1473,8 @@ float init_meta(Object *ob) /* return totsize */ /* make main array */ - next_object(0, 0, 0); - while(next_object(1, &base, &bob)) { + next_object(scene, 0, 0, 0); + while(next_object(scene, 1, &base, &bob)) { if(bob->type==OB_MBALL) { zero_size= 0; @@ -1482,8 +1484,7 @@ float init_meta(Object *ob) /* return totsize */ mat= imat= 0; mb= ob->data; - if(ob==G.obedit) ml= editelems.first; - else if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) ml= editelems.first; + if(mb->editelems) ml= mb->editelems->first; else ml= mb->elems.first; } else { @@ -1493,8 +1494,8 @@ float init_meta(Object *ob) /* return totsize */ splitIDname(bob->id.name+2, name, &nr); if( strcmp(obname, name)==0 ) { mb= bob->data; - if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) - ml= editelems.first; + + if(mb->editelems) ml= mb->editelems->first; else ml= mb->elems.first; } } @@ -2036,7 +2037,7 @@ void init_metaball_octal_tree(int depth) subdivide_metaball_octal_node(node, size[0], size[1], size[2], metaball_tree->depth); } -void metaball_polygonize(Object *ob) +void metaball_polygonize(Scene *scene, Object *ob) { PROCESS mbproc; MetaBall *mb; @@ -2059,7 +2060,7 @@ void metaball_polygonize(Object *ob) mainb= MEM_mallocN(sizeof(void *)*totelem, "mainb"); /* initialize all mainb (MetaElems) */ - totsize= init_meta(ob); + totsize= init_meta(scene, ob); if(metaball_tree){ free_metaball_octal_node(metaball_tree->first); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 77b9ea4fa2d..3facf975992 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -24,9 +24,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation * * ***** END GPL LICENSE BLOCK ***** */ @@ -58,7 +56,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" -#include "BKE_multires.h" #include "BKE_subsurf.h" #include "BKE_displist.h" #include "BKE_library.h" @@ -69,16 +66,22 @@ /* -- */ #include "BKE_object.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" - -#ifdef WITH_VERSE -#include "BKE_verse.h" -#endif #include "BLI_blenlib.h" #include "BLI_editVert.h" #include "BLI_arithb.h" + +EditMesh *BKE_mesh_get_editmesh(Mesh *me) +{ + return me->edit_mesh; +} + +void BKE_mesh_end_editmesh(Mesh *me, EditMesh *em) +{ +} + + void mesh_update_customdata_pointers(Mesh *me) { me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); @@ -143,8 +146,7 @@ void free_mesh(Mesh *me) if(me->bb) MEM_freeN(me->bb); if(me->mselect) MEM_freeN(me->mselect); - - if(me->mr) multires_free(me->mr); + if(me->edit_mesh) MEM_freeN(me->edit_mesh); } void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) @@ -194,11 +196,8 @@ Mesh *add_mesh(char *name) me->texflag= AUTOSPACE; me->flag= ME_TWOSIDED; me->bb= unit_boundbox(); - -#ifdef WITH_VERSE - me->vnode = NULL; -#endif - + me->drawflag= ME_DRAWEDGES|ME_DRAWFACES|ME_DRAWCREASES; + return me; } @@ -232,9 +231,6 @@ Mesh *copy_mesh(Mesh *me) } } - if(me->mr) - men->mr= multires_copy(me->mr); - men->mselect= NULL; men->bb= MEM_dupallocN(men->bb); @@ -242,10 +238,6 @@ Mesh *copy_mesh(Mesh *me) men->key= copy_key(me->key); if(men->key) men->key->from= (ID *)men; -#ifdef WITH_VERSE - men->vnode = NULL; -#endif - return men; } @@ -952,7 +944,8 @@ void nurbs_to_mesh(Object *ob) } -void mesh_delete_material_index(Mesh *me, int index) { +void mesh_delete_material_index(Mesh *me, int index) +{ int i; for (i=0; i<me->totface; i++) { @@ -962,7 +955,8 @@ void mesh_delete_material_index(Mesh *me, int index) { } } -void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) { +void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) +{ Mesh *me = meshOb->data; int i; @@ -976,7 +970,7 @@ void mesh_set_smooth_flag(Object *meshOb, int enableSmooth) { } } - DAG_object_flush_update(G.scene, meshOb, OB_RECALC_DATA); +// XXX do this in caller DAG_object_flush_update(scene, meshOb, OB_RECALC_DATA); } void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float **faceNors_r) @@ -1025,38 +1019,14 @@ void mesh_calc_normals(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3] { -#ifdef WITH_VERSE - if(me->vnode) { - struct VLayer *vlayer; - struct VerseVert *vvert; - unsigned int i, numVerts; - float (*cos)[3]; - - vlayer = find_verse_layer_type((VGeomData*)((VNode*)me->vnode)->data, VERTEX_LAYER); - - vvert = vlayer->dl.lb.first; - numVerts = vlayer->dl.da.count; - cos = MEM_mallocN(sizeof(*cos)*numVerts, "verse_vertexcos"); - - for(i=0; i<numVerts && vvert; vvert = vvert->next, i++) { - VECCOPY(cos[i], vvert->co); - } - - return cos; - } - else { -#endif - int i, numVerts = me->totvert; - float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1"); - - if (numVerts_r) *numVerts_r = numVerts; - for (i=0; i<numVerts; i++) - VECCOPY(cos[i], me->mvert[i].co); - - return cos; -#ifdef WITH_VERSE - } -#endif + int i, numVerts = me->totvert; + float (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "vertexcos1"); + + if (numVerts_r) *numVerts_r = numVerts; + for (i=0; i<numVerts; i++) + VECCOPY(cos[i], me->mvert[i].co); + + return cos; } float (*mesh_getRefKeyCos(Mesh *me, int *numVerts_r))[3] @@ -1191,6 +1161,48 @@ void free_uv_vert_map(UvVertMap *vmap) } } +/* Generates a map where the key is the vertex and the value is a list + of faces that use that vertex as a corner. The lists are allocated + from one memory pool. */ +void create_vert_face_map(ListBase **map, IndexNode **mem, const MFace *mface, const int totvert, const int totface) +{ + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totface; ++i){ + for(j = 0; j < (mface[i].v4?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&mface[i]))[j]], node); + } + } +} + +/* Generates a map where the key is the vertex and the value is a list + of edges that use that vertex as an endpoint. The lists are allocated + from one memory pool. */ +void create_vert_edge_map(ListBase **map, IndexNode **mem, const MEdge *medge, const int totvert, const int totedge) +{ + int i, j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totedge * 2, "vert edge map mem"); + node = *mem; + + /* Find the users */ + for(i = 0; i < totedge; ++i){ + for(j = 0; j < 2; ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[((unsigned int*)(&medge[i].v1))[j]], node); + } + } +} + /* Partial Mesh Visibility */ PartialVisibility *mesh_pmv_copy(PartialVisibility *pmv) { @@ -1246,7 +1258,7 @@ void mesh_pmv_revert(Object *ob, Mesh *me) MEM_freeN(me->pv->vert_map); me->pv->vert_map= NULL; - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); +// XXX do this in caller DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 7977e7b0160..6ebd68e990f 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -20,8 +20,6 @@ * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * -* The Original Code is: all of this file. -* * Contributor(s): Daniel Dunbar * Ton Roosendaal, * Ben Batt, @@ -77,9 +75,8 @@ #include "BKE_main.h" #include "BKE_anim.h" -#include "BKE_bad_level_calls.h" #include "BKE_bmesh.h" -#include "BKE_booleanops.h" +// XXX #include "BKE_booleanops.h" #include "BKE_cloth.h" #include "BKE_collision.h" #include "BKE_cdderivedmesh.h" @@ -89,6 +86,7 @@ #include "BKE_displist.h" #include "BKE_fluidsim.h" #include "BKE_global.h" +#include "BKE_multires.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_material.h" @@ -107,13 +105,18 @@ #include "BKE_shrinkwrap.h" #include "BKE_simple_deform.h" -#include "LOD_DependKludge.h" +//XXX #include "LOD_DependKludge.h" #include "LOD_decimation.h" +// XXX +static struct DerivedMesh *NewBooleanDerivedMesh() {return NULL;} + #include "CCGSubSurf.h" #include "RE_shader_ext.h" +//XXX #include "BIF_meshlaplacian.h" + /***/ static int noneModifier_isDisabled(ModifierData *md) @@ -169,7 +172,7 @@ static void curveModifier_foreachObjectLink( } static void curveModifier_updateDepgraph( - ModifierData *md, DagForest *forest, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { CurveModifierData *cmd = (CurveModifierData*) md; @@ -184,11 +187,11 @@ static void curveModifier_updateDepgraph( static void curveModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { CurveModifierData *cmd = (CurveModifierData*) md; - curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts, + curve_deform_verts(md->scene, cmd->object, ob, derivedData, vertexCos, numVerts, cmd->name, cmd->defaxis); } @@ -200,7 +203,7 @@ static void curveModifier_deformVertsEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); - curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts); + curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0); if(!derivedData) dm->release(dm); } @@ -244,7 +247,7 @@ static void latticeModifier_foreachObjectLink( walk(userData, ob, &lmd->object); } -static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, +static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -273,7 +276,7 @@ static void modifier_vgroup_cache(ModifierData *md, float (*vertexCos)[3]) static void latticeModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { LatticeModifierData *lmd = (LatticeModifierData*) md; @@ -292,7 +295,7 @@ static void latticeModifier_deformVertsEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); - latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts); + latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts, 0, 0); if(!derivedData) dm->release(dm); } @@ -420,10 +423,10 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, for(i = 0; i < maxFaces; ++i) faceMap[i] = i; if (ob) { - frac = bsystem_time(ob, (float)G.scene->r.cfra, + frac = bsystem_time(md->scene, ob, md->scene->r.cfra, bmd->start - 1.0f) / bmd->length; } else { - frac = G.scene->r.cfra - bmd->start / bmd->length; + frac = md->scene->r.cfra - bmd->start / bmd->length; } CLAMP(frac, 0.0, 1.0); @@ -613,7 +616,7 @@ static void maskModifier_foreachObjectLink( walk(userData, ob, &mmd->ob_arm); } -static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, +static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { MaskModifierData *mmd = (MaskModifierData *)md; @@ -999,7 +1002,7 @@ static void arrayModifier_foreachObjectLink( walk(userData, ob, &amd->offset_ob); } -static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, +static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { ArrayModifierData *amd = (ArrayModifierData*) md; @@ -1088,7 +1091,7 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldIndex, int copyNum) } static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, - Object *ob, DerivedMesh *dm, + Scene *scene, Object *ob, DerivedMesh *dm, int initFlags) { int i, j; @@ -1112,9 +1115,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, /* need to avoid infinite recursion here */ if(amd->start_cap && amd->start_cap != ob) - start_cap = mesh_get_derived_final(amd->start_cap, CD_MASK_MESH); + start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH); if(amd->end_cap && amd->end_cap != ob) - end_cap = mesh_get_derived_final(amd->end_cap, CD_MASK_MESH); + end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH); MTC_Mat4One(offset); @@ -1159,7 +1162,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist - makeDispListCurveTypes(amd->curve_ob, 0); + makeDispListCurveTypes(scene, amd->curve_ob, 0); } if(cu->path) length = scale*cu->path->totdist; @@ -1635,7 +1638,7 @@ static DerivedMesh *arrayModifier_applyModifier( DerivedMesh *result; ArrayModifierData *amd = (ArrayModifierData*) md; - result = arrayModifier_doArray(amd, ob, derivedData, 0); + result = arrayModifier_doArray(amd, md->scene, ob, derivedData, 0); if(result != derivedData) CDDM_calc_normals(result); @@ -1682,7 +1685,7 @@ static void mirrorModifier_foreachObjectLink( walk(userData, ob, &mmd->mirror_ob); } -static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, +static void mirrorModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { MirrorModifierData *mmd = (MirrorModifierData*) md; @@ -3461,7 +3464,7 @@ static int displaceModifier_isDisabled(ModifierData *md) } static void displaceModifier_updateDepgraph( - ModifierData *md, DagForest *forest, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { DisplaceModifierData *dmd = (DisplaceModifierData*) md; @@ -3683,7 +3686,7 @@ static void displaceModifier_do( static void displaceModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm; @@ -3782,7 +3785,7 @@ static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob, } static void uvprojectModifier_updateDepgraph(ModifierData *md, - DagForest *forest, Object *ob, DagNode *obNode) + DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { UVProjectModifierData *umd = (UVProjectModifierData*) md; int i; @@ -4059,11 +4062,11 @@ static DerivedMesh *decimateModifier_applyModifier( ModifierData *md, Object *ob, DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) { - DecimateModifierData *dmd = (DecimateModifierData*) md; + // DecimateModifierData *dmd = (DecimateModifierData*) md; DerivedMesh *dm = derivedData, *result = NULL; MVert *mvert; MFace *mface; - LOD_Decimation_Info lod; + // LOD_Decimation_Info lod; int totvert, totface; int a, numTris; @@ -4085,6 +4088,8 @@ static DerivedMesh *decimateModifier_applyModifier( goto exit; } + // XXX +#if 0 lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices"); lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals"); lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias"); @@ -4169,6 +4174,10 @@ static DerivedMesh *decimateModifier_applyModifier( MEM_freeN(lod.vertex_buffer); MEM_freeN(lod.vertex_normal_buffer); MEM_freeN(lod.triangle_index_buffer); +#else + modifier_setError(md, "Modifier not working yet in 2.5."); + goto exit; +#endif exit: return result; @@ -4362,7 +4371,7 @@ static void smoothModifier_do( static void smoothModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm; @@ -4461,7 +4470,7 @@ static void castModifier_foreachObjectLink( } static void castModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { CastModifierData *cmd = (CastModifierData*) md; @@ -4942,7 +4951,7 @@ static void castModifier_cuboid_do( static void castModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm = derivedData; CastModifierData *cmd = (CastModifierData *)md; @@ -5050,7 +5059,7 @@ static void waveModifier_foreachIDLink(ModifierData *md, Object *ob, } static void waveModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { WaveModifierData *wmd = (WaveModifierData*) md; @@ -5175,15 +5184,15 @@ static void wavemod_get_texture_coords(WaveModifierData *wmd, Object *ob, } } -static void waveModifier_do( - WaveModifierData *md, Object *ob, DerivedMesh *dm, +static void waveModifier_do(WaveModifierData *md, + Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { WaveModifierData *wmd = (WaveModifierData*) md; MVert *mvert = NULL; MDeformVert *dvert = NULL; int defgrp_index; - float ctime = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); + float ctime = bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); float minfac = (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow)); float lifefac = wmd->height; @@ -5345,7 +5354,7 @@ static void waveModifier_do( static void waveModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm; WaveModifierData *wmd = (WaveModifierData *)md; @@ -5361,7 +5370,7 @@ static void waveModifier_deformVerts( CDDM_calc_normals(dm); } - waveModifier_do(wmd, ob, dm, vertexCos, numVerts); + waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts); if(dm != derivedData) dm->release(dm); } @@ -5383,7 +5392,7 @@ static void waveModifier_deformVertsEM( CDDM_calc_normals(dm); } - waveModifier_do(wmd, ob, dm, vertexCos, numVerts); + waveModifier_do(wmd, md->scene, ob, dm, vertexCos, numVerts); if(dm != derivedData) dm->release(dm); } @@ -5435,7 +5444,7 @@ static void armatureModifier_foreachObjectLink( } static void armatureModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -5450,7 +5459,7 @@ static void armatureModifier_updateDepgraph( static void armatureModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { ArmatureModifierData *amd = (ArmatureModifierData*) md; @@ -5556,7 +5565,7 @@ static void hookModifier_foreachObjectLink( walk(userData, ob, &hmd->object); } -static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, +static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { HookModifierData *hmd = (HookModifierData*) md; @@ -5571,7 +5580,7 @@ static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, static void hookModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { HookModifierData *hmd = (HookModifierData*) md; float vec[3], mat[4][4]; @@ -5692,7 +5701,7 @@ static void hookModifier_deformVertsEM( if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data); - hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts); + hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0); if(!derivedData) dm->release(dm); } @@ -5701,9 +5710,9 @@ static void hookModifier_deformVertsEM( static void softbodyModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { - sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); + sbObjectStep(md->scene, ob, (float)md->scene->r.cfra, vertexCos, numVerts); } static int softbodyModifier_dependsOnTime(ModifierData *md) @@ -5744,7 +5753,7 @@ static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, return derivedData; } - result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); + result = clothModifier_do(clmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc); if(result) { @@ -5755,7 +5764,7 @@ static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, } static void clothModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { ClothModifierData *clmd = (ClothModifierData*) md; @@ -5764,7 +5773,7 @@ static void clothModifier_updateDepgraph( if(clmd) { - for(base = G.scene->base.first; base; base= base->next) + for(base = scene->base.first; base; base= base->next) { Object *ob1= base->object; if(ob1 != ob) @@ -5889,7 +5898,7 @@ static int collisionModifier_dependsOnTime(ModifierData *md) static void collisionModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { CollisionModifierData *collmd = (CollisionModifierData*) md; DerivedMesh *dm = NULL; @@ -5912,7 +5921,7 @@ static void collisionModifier_deformVerts( CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); - current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + current_time = bsystem_time (md->scene, ob, ( float ) md->scene->r.cfra, 0.0 ); if(G.rt > 0) printf("current_time %f, collmd->time %f\n", current_time, collmd->time); @@ -6051,11 +6060,9 @@ static int surfaceModifier_dependsOnTime(ModifierData *md) static void surfaceModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { SurfaceModifierData *surmd = (SurfaceModifierData*) md; - DerivedMesh *dm = NULL; - float current_time = 0; unsigned int numverts = 0, i = 0; if(surmd->dm) @@ -6121,7 +6128,7 @@ static void booleanModifier_foreachObjectLink( } static void booleanModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { BooleanModifierData *bmd = (BooleanModifierData*) md; @@ -6140,7 +6147,7 @@ static DerivedMesh *booleanModifier_applyModifier( { // XXX doesn't handle derived data BooleanModifierData *bmd = (BooleanModifierData*) md; - DerivedMesh *dm = mesh_get_derived_final(bmd->object, CD_MASK_BAREMESH); + DerivedMesh *dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_BAREMESH); /* we do a quick sanity check */ if(dm && (derivedData->getNumFaces(derivedData) > 3) @@ -6258,15 +6265,56 @@ static int is_last_displist(Object *ob) return 0; } + +static DerivedMesh *get_original_dm(Scene *scene, Object *ob, float (*vertexCos)[3], int orco) +{ + DerivedMesh *dm= NULL; + + if(ob->type==OB_MESH) { + dm = CDDM_from_mesh((Mesh*)(ob->data), ob); + + if(vertexCos) { + CDDM_apply_vert_coords(dm, vertexCos); + //CDDM_calc_normals(dm); + } + + if(orco) + DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); + } + else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)) { + Object *tmpobj; + Curve *tmpcu; + + if(is_last_displist(ob)) { + /* copies object and modifiers (but not the data) */ + tmpobj= copy_object(ob); + tmpcu = (Curve *)tmpobj->data; + tmpcu->id.us--; + + /* copies the data */ + tmpobj->data = copy_curve((Curve *) ob->data); + + makeDispListCurveTypes(scene, tmpobj, 1); + nurbs_to_mesh(tmpobj); + + dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); + //CDDM_calc_normals(dm); + + free_libblock_us(&G.main->object, tmpobj); + } + } + + return dm; +} + /* saves the current emitter state for a particle system and calculates particles */ static void particleSystemModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm = derivedData; ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md; ParticleSystem * psys=0; - Mesh *me; int needsFree=0; if(ob->particlesystem.first) @@ -6274,54 +6322,16 @@ static void particleSystemModifier_deformVerts( else return; - /* multires check */ - if(ob->type == OB_MESH) { - me= (Mesh*)ob->data; - if(me->mr && me->mr->current != 1) - modifier_setError(md, - "Particles only supported on first multires level."); - } - if(!psys_check_enabled(ob, psys)) return; - if(dm==0){ - if(ob->type==OB_MESH){ - dm = CDDM_from_mesh((Mesh*)(ob->data), ob); - - CDDM_apply_vert_coords(dm, vertexCos); - //CDDM_calc_normals(dm); - - DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); - - needsFree=1; - } - else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)){ - Object *tmpobj; - Curve *tmpcu; - - if(is_last_displist(ob)){ - /* copies object and modifiers (but not the data) */ - tmpobj= copy_object( ob ); - tmpcu = (Curve *)tmpobj->data; - tmpcu->id.us--; - - /* copies the data */ - tmpobj->data = copy_curve( (Curve *) ob->data ); + if(dm==0) { + dm= get_original_dm(md->scene, ob, vertexCos, 1); - makeDispListCurveTypes( tmpobj, 1 ); - nurbs_to_mesh( tmpobj ); - - dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj); - //CDDM_calc_normals(dm); - - free_libblock_us( &G.main->object, tmpobj ); + if(!dm) + return; - needsFree=1; - } - else return; - } - else return; + needsFree= 1; } /* clear old dm */ @@ -6349,8 +6359,7 @@ static void particleSystemModifier_deformVerts( psmd->dm->getNumFaces(psmd->dm)!=psmd->totdmface){ /* in file read dm hasn't really changed but just wasn't saved in file */ - psys->recalc |= PSYS_RECALC_HAIR; - psys->recalc |= PSYS_DISTR; + psys->recalc |= PSYS_RECALC_RESET; psmd->flag |= eParticleSystemFlag_DM_changed; psmd->totdmvert= psmd->dm->getNumVerts(psmd->dm); @@ -6359,7 +6368,7 @@ static void particleSystemModifier_deformVerts( } if(psys){ - particle_system_update(ob,psys); + particle_system_update(md->scene, ob, psys); psmd->flag |= eParticleSystemFlag_psys_updated; psmd->flag &= ~eParticleSystemFlag_DM_changed; } @@ -6407,7 +6416,7 @@ static int particleInstanceModifier_dependsOnTime(ModifierData *md) return 0; } static void particleInstanceModifier_updateDepgraph(ModifierData *md, DagForest *forest, - Object *ob, DagNode *obNode) + Scene *scene,Object *ob, DagNode *obNode) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md; @@ -6475,7 +6484,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( maxvert=totvert*totpart; maxface=totface*totpart; - psys->lattice=psys_get_lattice(ob, psys); + psys->lattice=psys_get_lattice(md->scene, ob, psys); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){ @@ -6510,7 +6519,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( state.time=(mv->co[0]-min_co)/(max_co-min_co); if(trackneg) state.time=1.0f-state.time; - psys_get_particle_on_path(pimd->ob,psys,first_particle + i/totvert,&state,1); + psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); mv->co[0] = 0.0; @@ -6532,7 +6541,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( } else{ state.time=-1.0; - psys_get_particle_state(pimd->ob,psys,i/totvert,&state,1); + psys_get_particle_state(md->scene, pimd->ob, psys, i/totvert, &state,1); } QuatMulVecf(state.rot,mv->co); @@ -6584,8 +6593,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier( CDDM_calc_normals(result); if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } return result; @@ -7203,7 +7212,7 @@ static DerivedMesh * explodeModifier_splitEdges(ExplodeModifierData *emd, Derive } static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, - ParticleSystemModifierData *psmd, Object *ob, + ParticleSystemModifierData *psmd, Scene *scene, Object *ob, DerivedMesh *to_explode) { DerivedMesh *explode, *dm=to_explode; @@ -7227,9 +7236,9 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, timestep= psys_get_timestep(part); if(part->flag & PART_GLOB_TIME) - cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0); + cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); else - cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0); + cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); /* hash table for vertice <-> particle relations */ vertpahash= BLI_edgehash_new(); @@ -7267,7 +7276,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ Mat4Invert(imat,ob->obmat); - psmd->psys->lattice = psys_get_lattice(ob, psmd->psys); + psmd->psys->lattice = psys_get_lattice(scene, ob, psmd->psys); /* duplicate & displace vertices */ ehi= BLI_edgehashIterator_new(vertpahash); @@ -7295,7 +7304,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, Mat4MulVecfl(ob->obmat,loc0); state.time=cfra; - psys_get_particle_state(ob,psmd->psys,i,&state,1); + psys_get_particle_state(scene, ob, psmd->psys, i, &state,1); vertco=CDDM_get_vert(explode,v)->co; @@ -7360,8 +7369,8 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, CDDM_calc_normals(explode); if(psmd->psys->lattice){ - end_latt_deform(); - psmd->psys->lattice=0; + end_latt_deform(psmd->psys->lattice); + psmd->psys->lattice= NULL; } return explode; @@ -7411,7 +7420,7 @@ static DerivedMesh * explodeModifier_applyModifier( if(emd->flag & eExplodeFlag_EdgeSplit){ int *facepa = emd->facepa; DerivedMesh *splitdm=explodeModifier_splitEdges(emd,dm); - DerivedMesh *explode=explodeModifier_explodeMesh(emd,psmd,ob,splitdm); + DerivedMesh *explode=explodeModifier_explodeMesh(emd, psmd, md->scene, ob, splitdm); MEM_freeN(emd->facepa); emd->facepa=facepa; @@ -7419,7 +7428,7 @@ static DerivedMesh * explodeModifier_applyModifier( return explode; } else - return explodeModifier_explodeMesh(emd,psmd,ob,derivedData); + return explodeModifier_explodeMesh(emd, psmd, md->scene, ob, derivedData); } return derivedData; } @@ -7465,7 +7474,7 @@ static DerivedMesh * fluidsimModifier_applyModifier( return derivedData; } - result = fluidsimModifier_do(fluidmd, ob, derivedData, useRenderParams, isFinalCalc); + result = fluidsimModifier_do(fluidmd, md->scene, ob, derivedData, useRenderParams, isFinalCalc); if(result) { @@ -7476,7 +7485,7 @@ static DerivedMesh * fluidsimModifier_applyModifier( } static void fluidsimModifier_updateDepgraph( - ModifierData *md, DagForest *forest, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { FluidsimModifierData *fluidmd= (FluidsimModifierData*) md; @@ -7486,7 +7495,7 @@ static void fluidsimModifier_updateDepgraph( { if(fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) { - for(base = G.scene->base.first; base; base= base->next) + for(base = scene->base.first; base; base= base->next) { Object *ob1= base->object; if(ob1 != ob) @@ -7568,7 +7577,7 @@ static void meshdeformModifier_foreachObjectLink( } static void meshdeformModifier_updateDepgraph( - ModifierData *md, DagForest *forest, Object *ob, + ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; @@ -7639,25 +7648,36 @@ static void meshdeformModifier_do( float (*vertexCos)[3], int numVerts) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; - float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; - float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3]; - int a, b, totvert, totcagevert, defgrp_index; + Mesh *me= ob->data; DerivedMesh *tmpdm, *cagedm; MDeformVert *dvert = NULL; MDeformWeight *dw; + EditMesh *em = BKE_mesh_get_editmesh(me); MVert *cagemvert; - + float imat[4][4], cagemat[4][4], iobmat[4][4], icagemat[3][3], cmat[4][4]; + float weight, totweight, fac, co[3], *weights, (*dco)[3], (*bindcos)[3]; + int a, b, totvert, totcagevert, defgrp_index; + if(!mmd->object || (!mmd->bindcos && !mmd->needbind)) return; /* get cage derivedmesh */ - if(mmd->object == G.obedit) { - tmpdm= editmesh_get_derived_cage_and_final(&cagedm, 0); + if(em) { + tmpdm= editmesh_get_derived_cage_and_final(md->scene, ob, em, &cagedm, 0); if(tmpdm) tmpdm->release(tmpdm); + BKE_mesh_end_editmesh(me, em); } else cagedm= mmd->object->derivedFinal; + + /* if we don't have one computed, use derivedmesh from data + * without any modifiers */ + if(!cagedm) { + cagedm= get_original_dm(md->scene, mmd->object, NULL, 0); + if(cagedm) + cagedm->needsFree= 1; + } if(!cagedm) return; @@ -7676,7 +7696,7 @@ static void meshdeformModifier_do( /* progress bar redraw can make this recursive .. */ if(!recursive) { recursive = 1; - harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); + //XXX harmonic_coordinates_bind(mmd, vertexCos, numVerts, cagemat); recursive = 0; } } @@ -7788,7 +7808,7 @@ static void meshdeformModifier_do( static void meshdeformModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) + float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm; @@ -7822,6 +7842,60 @@ static void meshdeformModifier_deformVertsEM( dm->release(dm); } +/* Multires */ +static void multiresModifier_initData(ModifierData *md) +{ + MultiresModifierData *mmd = (MultiresModifierData*)md; + + mmd->lvl = mmd->totlvl = 1; +} + +static void multiresModifier_freeData(ModifierData *md) +{ + MultiresModifierData *mmd = (MultiresModifierData*)md; + + if(mmd->undo_verts) + MEM_freeN(mmd->undo_verts); +} + +static void multiresModifier_copyData(ModifierData *md, ModifierData *target) +{ + MultiresModifierData *mmd = (MultiresModifierData*) md; + MultiresModifierData *tmmd = (MultiresModifierData*) target; + + tmmd->totlvl = mmd->totlvl; + tmmd->lvl = mmd->lvl; +} + +static DerivedMesh *multiresModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, + int useRenderParams, int isFinalCalc) +{ + MultiresModifierData *mmd = (MultiresModifierData*)md; + Mesh *me = get_mesh(ob); + DerivedMesh *final; + + /* TODO: for now just skip a level1 mesh */ + if(mmd->lvl == 1) + return dm; + + final = multires_dm_create_from_derived(mmd, dm, me, useRenderParams, isFinalCalc); + if(mmd->undo_signal && mmd->undo_verts && mmd->undo_verts_tot == final->getNumVerts(final)) { + int i; + MVert *dst = CDDM_get_verts(final); + for(i = 0; i < mmd->undo_verts_tot; ++i) { + VecCopyf(dst[i].co, mmd->undo_verts[i].co); + } + CDDM_calc_normals(final); + + MultiresDM_mark_as_modified(final); + + MEM_freeN(mmd->undo_verts); + mmd->undo_signal = 0; + mmd->undo_verts = NULL; + } + + return final; +} /* Shrinkwrap */ @@ -7884,7 +7958,7 @@ static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, O walk(userData, ob, &smd->auxTarget); } -static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm = NULL; CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); @@ -7897,14 +7971,14 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dm != NULL && (dataMask & CD_MVERT)) + if(dm != NULL && (dataMask & (1<<CD_MVERT))) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); } } - shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, dm, vertexCos, numVerts); + shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts); if(dm) dm->release(dm); @@ -7922,20 +7996,20 @@ static void shrinkwrapModifier_deformVertsEM(ModifierData *md, Object *ob, EditM else if(ob->type==OB_LATTICE) dm = NULL; else return; - if(dm != NULL && (dataMask & CD_MVERT)) + if(dm != NULL && (dataMask & (1<<CD_MVERT))) { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); } } - shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, ob, dm, vertexCos, numVerts); + shrinkwrapModifier_deform((ShrinkwrapModifierData*)md, md->scene, ob, dm, vertexCos, numVerts); if(dm) dm->release(dm); } -static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode) +static void shrinkwrapModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; @@ -7990,7 +8064,7 @@ static void simpledeformModifier_foreachObjectLink(ModifierData *md, Object *ob, walk(userData, ob, &smd->origin); } -static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode) +static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *forest, Scene *scene, Object *ob, DagNode *obNode) { SimpleDeformModifierData *smd = (SimpleDeformModifierData*)md; @@ -7998,7 +8072,7 @@ static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *for dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier"); } -static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc) { DerivedMesh *dm = NULL; CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); @@ -8430,6 +8504,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->foreachObjectLink = simpledeformModifier_foreachObjectLink; mti->updateDepgraph = simpledeformModifier_updateDepgraph; + mti = INIT_TYPE(Multires); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData; + mti->initData = multiresModifier_initData; + mti->freeData = multiresModifier_freeData; + mti->copyData = multiresModifier_copyData; + mti->applyModifier = multiresModifier_applyModifier; + typeArrInit = 0; #undef INIT_TYPE } @@ -8511,8 +8593,6 @@ void modifiers_clearErrors(Object *ob) qRedraw = 1; } } - - if (qRedraw) allqueue(REDRAWBUTSEDIT, 0); } void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, @@ -8578,7 +8658,6 @@ void modifier_setError(ModifierData *md, char *format, ...) md->error = BLI_strdup(buffer); - allqueue(REDRAWBUTSEDIT, 0); } /* used for buttons, to find out if the 'draw deformed in editmode' option is @@ -8647,7 +8726,7 @@ LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) if(mti->requiredDataMask) mask = mti->requiredDataMask(md); - BLI_linklist_prepend(&dataMasks, (void *)mask); + BLI_linklist_prepend(&dataMasks, SET_INT_IN_POINTER(mask)); } /* build the list of required data masks - each mask in the list must @@ -8658,14 +8737,14 @@ LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) */ for(curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) { if(prev) { - CustomDataMask prev_mask = (CustomDataMask)prev->link; - CustomDataMask curr_mask = (CustomDataMask)curr->link; + CustomDataMask prev_mask = (CustomDataMask)GET_INT_FROM_POINTER(prev->link); + CustomDataMask curr_mask = (CustomDataMask)GET_INT_FROM_POINTER(curr->link); - curr->link = (void *)(curr_mask | prev_mask); + curr->link = SET_INT_IN_POINTER(curr_mask | prev_mask); } else { - CustomDataMask curr_mask = (CustomDataMask)curr->link; + CustomDataMask curr_mask = (CustomDataMask)GET_INT_FROM_POINTER(curr->link); - curr->link = (void *)(curr_mask | dataMask); + curr->link = SET_INT_IN_POINTER(curr_mask | dataMask); } } @@ -8806,14 +8885,15 @@ int modifier_isDeformer(ModifierData *md) return 0; } -int modifiers_isDeformed(Object *ob) +int modifiers_isDeformed(Scene *scene, Object *ob) { ModifierData *md = modifiers_getVirtualModifierList(ob); for (; md; md=md->next) { - if(ob==G.obedit && (md->mode & eModifierMode_Editmode)==0); - else if(modifier_isDeformer(md)) - return 1; + if(ob==scene->obedit && (md->mode & eModifierMode_Editmode)==0); + else + if(modifier_isDeformer(md)) + return 1; } return 0; } @@ -8846,8 +8926,10 @@ void modifier_freeTemporaryData(ModifierData *md) if(md->type == eModifierType_Armature) { ArmatureModifierData *amd= (ArmatureModifierData*)md; - if(amd->prevCos) + if(amd->prevCos) { MEM_freeN(amd->prevCos); + amd->prevCos= NULL; + } } } diff --git a/source/blender/blenkernel/intern/multires-firstlevel.c b/source/blender/blenkernel/intern/multires-firstlevel.c deleted file mode 100644 index 3d417565eb1..00000000000 --- a/source/blender/blenkernel/intern/multires-firstlevel.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2006 by Nicholas Bishop - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * - * Deals with the first-level data in multires (edge flags, weights, and UVs) - * - * multires.h - * - */ - -#include "DNA_customdata_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BIF_editmesh.h" - -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_mesh.h" -#include "BKE_multires.h" - -#include "BLI_editVert.h" - -#include "MEM_guardedalloc.h" - -#include "blendef.h" - -#include <string.h> - -MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl); -MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl); -void multires_update_edge_flags(Mesh *me, EditMesh *em); -void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease); - -/*********** Generic ***********/ - -CustomDataMask cdmask(const int type) -{ - if(type == CD_MDEFORMVERT) - return CD_MASK_MDEFORMVERT; - else if(type == CD_MTFACE) - return CD_MASK_MTFACE; - return -1; -} - -char type_ok(const int type) -{ - return (type == CD_MDEFORMVERT) || (type == CD_MTFACE); -} - -/* Copy vdata or fdata from Mesh or EditMesh to Multires. */ -void multires_update_customdata(MultiresLevel *lvl1, EditMesh *em, CustomData *src, CustomData *dst, const int type) -{ - if(src && dst && type_ok(type)) { - const int tot= (type == CD_MDEFORMVERT ? lvl1->totvert : lvl1->totface); - int i; - - CustomData_free(dst, tot); - - if(CustomData_has_layer(src, type)) { - if(em) { - EditVert *eve= G.editMesh->verts.first; - EditFace *efa= G.editMesh->faces.first; - CustomData_copy(src, dst, cdmask(type), CD_CALLOC, tot); - for(i=0; i<tot; ++i) { - if(type == CD_MDEFORMVERT) { - CustomData_from_em_block(&G.editMesh->vdata, dst, eve->data, i); - eve= eve->next; - } - else if(type == CD_MTFACE) { - CustomData_from_em_block(&G.editMesh->fdata, dst, efa->data, i); - efa= efa->next; - } - } - } - else - CustomData_copy(src, dst, cdmask(type), CD_DUPLICATE, tot); - } - } -} - -/* Uses subdivide_dverts or subdivide_mtfaces to subdivide src to match lvl_end. Does not free src. */ -void *subdivide_customdata_to_level(void *src, MultiresLevel *lvl_start, - MultiresLevel *lvl_end, const int type) -{ - if(src && lvl_start && lvl_end && type_ok(type)) { - MultiresLevel *lvl; - void *cr_data= NULL, *pr_data= NULL; - - pr_data= src; - for(lvl= lvl_start; lvl && lvl != lvl_end; lvl= lvl->next) { - if(type == CD_MDEFORMVERT) - cr_data= subdivide_dverts(pr_data, lvl); - else if(type == CD_MTFACE) - cr_data= subdivide_mtfaces(pr_data, lvl); - - /* Free previous subdivision level's data */ - if(lvl != lvl_start) { - if(type == CD_MDEFORMVERT) - free_dverts(pr_data, lvl->totvert); - else if(type == CD_MTFACE) - MEM_freeN(pr_data); - } - - pr_data= cr_data; - cr_data= NULL; - } - - return pr_data; - } - - return NULL; -} - -/* Directly copy src into dst (handles both Mesh and EditMesh) */ -void customdata_to_mesh(Mesh *me, EditMesh *em, CustomData *src, CustomData *dst, const int tot, const int type) -{ - if(me && me->mr && src && dst && type_ok(type)) { - if(em) { - int i; - EditVert *eve= em->verts.first; - EditFace *efa= em->faces.first; - CustomData_copy(src, dst, cdmask(type), CD_CALLOC, 0); - - for(i=0; i<tot; ++i) { - if(type == CD_MDEFORMVERT) { - CustomData_to_em_block(src, dst, i, &eve->data); - eve= eve->next; - } - else if(type == CD_MTFACE) { - CustomData_to_em_block(src, dst, i, &efa->data); - efa= efa->next; - } - } - } else { - CustomData_merge(src, dst, cdmask(type), CD_DUPLICATE, tot); - } - } -} - -/* Subdivide vdata or fdata from Multires into either Mesh or EditMesh. */ -void multires_customdata_to_mesh(Mesh *me, EditMesh *em, MultiresLevel *lvl, CustomData *src, - CustomData *dst, const int type) -{ - if(me && me->mr && lvl && src && dst && type_ok(type) && - CustomData_has_layer(src, type)) { - const int tot= (type == CD_MDEFORMVERT ? lvl->totvert : lvl->totface); - if(lvl == me->mr->levels.first) { - customdata_to_mesh(me, em, src, dst, tot, type); - } - else { - CustomData cdf; - const int count = CustomData_number_of_layers(src, type); - int i; - - /* Construct a new CustomData containing the subdivided data */ - CustomData_copy(src, &cdf, cdmask(type), CD_ASSIGN, tot); - for(i=0; i<count; ++i) { - void *layer= CustomData_get_layer_n(&cdf, type, i); - CustomData_set_layer_n(&cdf, type, i, - subdivide_customdata_to_level(layer, me->mr->levels.first, lvl, type)); - } - - customdata_to_mesh(me, em, &cdf, dst, tot, type); - CustomData_free(&cdf, tot); - } - } -} - -/* Subdivide the first-level customdata up to cr_lvl, then delete the original data */ -void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl) -{ - MultiresLevel *lvl1= mr->levels.first; - MDeformVert *dverts= NULL; - CustomData cdf; - int i; - - /* dverts */ - dverts= subdivide_customdata_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT), - lvl1, cr_lvl, CD_MDEFORMVERT); - if(dverts) { - CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert); - CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert); - } - - /* mtfaces */ - CustomData_copy(&mr->fdata, &cdf, CD_MASK_MTFACE, CD_ASSIGN, cr_lvl->totface); - for(i=0; i<CustomData_number_of_layers(&mr->fdata, CD_MTFACE); ++i) { - MTFace *mtfaces= - subdivide_customdata_to_level(CustomData_get_layer_n(&mr->fdata, CD_MTFACE, i), - lvl1, cr_lvl, CD_MTFACE); - if(mtfaces) - CustomData_set_layer_n(&cdf, CD_MTFACE, i, mtfaces); - } - - CustomData_free(&mr->fdata, lvl1->totface); - mr->fdata= cdf; -} - -/* Update all special first-level data, if the first-level is active */ -void multires_update_first_level(Mesh *me, EditMesh *em) -{ - if(me && me->mr && me->mr->current == 1) { - multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata, - &me->mr->vdata, CD_MDEFORMVERT); - multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata, - &me->mr->fdata, CD_MTFACE); - multires_update_edge_flags(me, em); - } -} - -/*********** Multires.edge_flags ***********/ -void multires_update_edge_flags(Mesh *me, EditMesh *em) -{ - MultiresLevel *lvl= me->mr->levels.first; - EditEdge *eed= NULL; - int i; - - if(em) eed= em->edges.first; - for(i=0; i<lvl->totedge; ++i) { - if(em) { - me->mr->edge_flags[i]= 0; - eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]); - eed= eed->next; - } - else { - me->mr->edge_flags[i]= me->medge[i].flag; - me->mr->edge_creases[i]= me->medge[i].crease; - } - } -} - - - -/*********** Multires.vdata ***********/ - -/* MDeformVert */ - -/* Add each weight from in to out. Scale each weight by w. */ -void multires_add_dvert(MDeformVert *out, const MDeformVert *in, const float w) -{ - if(out && in) { - int i, j; - char found; - - for(i=0; i<in->totweight; ++i) { - found= 0; - for(j=0; j<out->totweight; ++j) { - if(out->dw[j].def_nr==in->dw[i].def_nr) { - out->dw[j].weight += in->dw[i].weight * w; - found= 1; - } - } - if(!found) { - MDeformWeight *newdw= MEM_callocN(sizeof(MDeformWeight)*(out->totweight+1), - "multires dvert"); - if(out->dw) { - memcpy(newdw, out->dw, sizeof(MDeformWeight)*out->totweight); - MEM_freeN(out->dw); - } - - out->dw= newdw; - out->dw[out->totweight].weight= in->dw[i].weight * w; - out->dw[out->totweight].def_nr= in->dw[i].def_nr; - - ++out->totweight; - } - } - } -} - -/* Takes an input array of dverts and subdivides them (linear) using the topology of lvl */ -MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl) -{ - if(lvl && lvl->next) { - MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->next->totvert, "dvert prop array"); - int i, j; - - /* Copy lower level */ - for(i=0; i<lvl->totvert; ++i) - multires_add_dvert(&out[i], &src[i], 1); - /* Edge verts */ - for(i=0; i<lvl->totedge; ++i) { - for(j=0; j<2; ++j) - multires_add_dvert(&out[lvl->totvert+i], &src[lvl->edges[i].v[j]],0.5); - } - - /* Face verts */ - for(i=0; i<lvl->totface; ++i) { - for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j) - multires_add_dvert(&out[lvl->totvert + lvl->totedge + i], - &src[lvl->faces[i].v[j]], - lvl->faces[i].v[3]?0.25:(1.0f/3.0f)); - } - - return out; - } - - return NULL; -} - - - -/*********** Multires.fdata ***********/ - -/* MTFace */ - -void multires_uv_avg2(float out[2], const float a[2], const float b[2]) -{ - int i; - for(i=0; i<2; ++i) - out[i] = (a[i] + b[i]) / 2.0f; -} - -/* Takes an input array of mtfaces and subdivides them (linear) using the topology of lvl */ -MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl) -{ - if(lvl && lvl->next) { - MTFace *out= MEM_callocN(sizeof(MultiresColFace)*lvl->next->totface,"Multirescolfaces"); - int i, j, curf; - - for(i=0, curf=0; i<lvl->totface; ++i) { - const char sides= lvl->faces[i].v[3]?4:3; - float cntr[2]= {0, 0}; - - /* Find average uv coord of the current face */ - for(j=0; j<sides; ++j) { - cntr[0]+= src[i].uv[j][0]; - cntr[1]+= src[i].uv[j][1]; - } - cntr[0]/= sides; - cntr[1]/= sides; - - for(j=0; j<sides; ++j, ++curf) { - out[curf]= src[i]; - - multires_uv_avg2(out[curf].uv[0], src[i].uv[j], src[i].uv[j==0?sides-1:j-1]); - - out[curf].uv[1][0]= src[i].uv[j][0]; - out[curf].uv[1][1]= src[i].uv[j][1]; - - multires_uv_avg2(out[curf].uv[2], src[i].uv[j], src[i].uv[j==sides-1?0:j+1]); - - out[curf].uv[3][0]= cntr[0]; - out[curf].uv[3][1]= cntr[1]; - } - } - - return out; - } - - return NULL; -} - -void multires_delete_layer(Mesh *me, CustomData *cd, const int type, int n) -{ - if(me && me->mr && cd) { - MultiresLevel *lvl1= me->mr->levels.first; - - multires_update_levels(me, 0); - - CustomData_set_layer_active(cd, type, n); - CustomData_free_layer_active(cd, type, lvl1->totface); - - multires_level_to_mesh(OBACT, me, 0); - } -} - -void multires_add_layer(Mesh *me, CustomData *cd, const int type, const int n) -{ - if(me && me->mr && cd) { - multires_update_levels(me, 0); - - if(CustomData_has_layer(cd, type)) - CustomData_add_layer(cd, type, CD_DUPLICATE, CustomData_get_layer(cd, type), - current_level(me->mr)->totface); - else - CustomData_add_layer(cd, type, CD_DEFAULT, NULL, current_level(me->mr)->totface); - - CustomData_set_layer_active(cd, type, n); - multires_level_to_mesh(OBACT, me, 0); - } -} diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4d312632b1a..b1387281cf5 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -32,1278 +32,1544 @@ #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" -#include "DNA_vec_types.h" - -#include "BIF_editmesh.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "BLI_editVert.h" +#include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_multires.h" - -#include "blendef.h" -#include "editmesh.h" +#include "BKE_object.h" +#include "BKE_subsurf.h" #include <math.h> +#include <string.h> -/* Returns the active multires level (currently applied to the mesh) */ -MultiresLevel *current_level(Multires *mr) -{ - return BLI_findlink(&mr->levels, mr->current - 1); -} +/* MULTIRES MODIFIER */ +static const int multires_max_levels = 13; +static const int multires_quad_tot[] = {4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409}; +static const int multires_side_tot[] = {2, 3, 5, 9, 17, 33, 65, 129, 257, 513, 1025, 2049, 4097}; -/* Returns the nth multires level, starting at 1 */ -MultiresLevel *multires_level_n(Multires *mr, int n) +MultiresModifierData *find_multires_modifier(Object *ob) { - if(mr) - return BLI_findlink(&mr->levels, n - 1); - else - return NULL; -} + ModifierData *md; + MultiresModifierData *mmd = NULL; -/* Free and clear the temporary connectivity data */ -static void multires_free_temp_data(MultiresLevel *lvl) -{ - if(lvl) { - if(lvl->edge_boundary_states) MEM_freeN(lvl->edge_boundary_states); - if(lvl->vert_edge_map) MEM_freeN(lvl->vert_edge_map); - if(lvl->vert_face_map) MEM_freeN(lvl->vert_face_map); - if(lvl->map_mem) MEM_freeN(lvl->map_mem); - - lvl->edge_boundary_states = NULL; - lvl->vert_edge_map = lvl->vert_face_map = NULL; - lvl->map_mem = NULL; + for(md = ob->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) { + mmd = (MultiresModifierData*)md; + break; + } } + + return mmd; + } -/* Does not actually free lvl itself */ -void multires_free_level(MultiresLevel *lvl) +int multiresModifier_switch_level(Object *ob, const int distance) { - if(lvl) { - if(lvl->faces) MEM_freeN(lvl->faces); - if(lvl->edges) MEM_freeN(lvl->edges); - if(lvl->colfaces) MEM_freeN(lvl->colfaces); - - multires_free_temp_data(lvl); + MultiresModifierData *mmd = find_multires_modifier(ob); + + if(mmd) { + mmd->lvl += distance; + if(mmd->lvl < 1) mmd->lvl = 1; + else if(mmd->lvl > mmd->totlvl) mmd->lvl = mmd->totlvl; + /* XXX: DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + object_handle_update(ob);*/ + return 1; } + else + return 0; } -void multires_free(Multires *mr) +/* XXX */ +#if 0 +void multiresModifier_join(Object *ob) { - if(mr) { - MultiresLevel* lvl= mr->levels.first; - - /* Free the first-level data */ - if(lvl) { - CustomData_free(&mr->vdata, lvl->totvert); - CustomData_free(&mr->fdata, lvl->totface); - MEM_freeN(mr->edge_flags); - MEM_freeN(mr->edge_creases); + Base *base = NULL; + int highest_lvl = 0; + + /* First find the highest level of subdivision */ + base = FIRSTBASE; + while(base) { + if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) { + ModifierData *md; + for(md = base->object->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) { + int totlvl = ((MultiresModifierData*)md)->totlvl; + if(totlvl > highest_lvl) + highest_lvl = totlvl; + + /* Ensure that all updates are processed */ + multires_force_update(base->object); + } + } } + base = base->next; + } - while(lvl) { - multires_free_level(lvl); - lvl= lvl->next; - } + /* No multires meshes selected */ + if(highest_lvl == 0) + return; - MEM_freeN(mr->verts); + /* Subdivide all the displacements to the highest level */ + base = FIRSTBASE; + while(base) { + if(TESTBASELIB_BGMODE(base) && base->object->type==OB_MESH) { + ModifierData *md = NULL; + MultiresModifierData *mmd = NULL; - BLI_freelistN(&mr->levels); + for(md = base->object->modifiers.first; md; md = md->next) { + if(md->type == eModifierType_Multires) + mmd = (MultiresModifierData*)md; + } - MEM_freeN(mr); - } -} + /* If the object didn't have multires enabled, give it a new modifier */ + if(!mmd) { + md = base->object->modifiers.first; + + while(md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) + md = md->next; + + mmd = (MultiresModifierData*)modifier_new(eModifierType_Multires); + BLI_insertlinkbefore(&base->object->modifiers, md, mmd); + } -static MultiresLevel *multires_level_copy(MultiresLevel *orig) -{ - if(orig) { - MultiresLevel *lvl= MEM_dupallocN(orig); - - lvl->next= lvl->prev= NULL; - lvl->faces= MEM_dupallocN(orig->faces); - lvl->colfaces= MEM_dupallocN(orig->colfaces); - lvl->edges= MEM_dupallocN(orig->edges); - lvl->edge_boundary_states = NULL; - lvl->vert_edge_map= lvl->vert_face_map= NULL; - lvl->map_mem= NULL; - - return lvl; + if(mmd) + multiresModifier_subdivide(mmd, base->object, highest_lvl - mmd->totlvl, 0, 0); + } + base = base->next; } - return NULL; } +#endif -Multires *multires_copy(Multires *orig) +/* Returns 0 on success, 1 if the src's totvert doesn't match */ +int multiresModifier_reshape(MultiresModifierData *mmd, Object *dst, Object *src) { - const CustomDataMask vdata_mask= CD_MASK_MDEFORMVERT; + Mesh *src_me = get_mesh(src); + DerivedMesh *mrdm = dst->derivedFinal; - if(orig) { - Multires *mr= MEM_dupallocN(orig); - MultiresLevel *lvl; - - mr->levels.first= mr->levels.last= NULL; - - for(lvl= orig->levels.first; lvl; lvl= lvl->next) - BLI_addtail(&mr->levels, multires_level_copy(lvl)); + if(mrdm && mrdm->getNumVerts(mrdm) == src_me->totvert) { + MVert *mvert = CDDM_get_verts(mrdm); + int i; - mr->verts= MEM_dupallocN(orig->verts); - - lvl= mr->levels.first; - if(lvl) { - CustomData_copy(&orig->vdata, &mr->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert); - CustomData_copy(&orig->fdata, &mr->fdata, CD_MASK_MTFACE, CD_DUPLICATE, lvl->totface); - mr->edge_flags= MEM_dupallocN(orig->edge_flags); - mr->edge_creases= MEM_dupallocN(orig->edge_creases); - } - - return mr; - } - return NULL; -} + for(i = 0; i < src_me->totvert; ++i) + VecCopyf(mvert[i].co, src_me->mvert[i].co); + mrdm->needsFree = 1; + MultiresDM_mark_as_modified(mrdm); + mrdm->release(mrdm); + dst->derivedFinal = NULL; -static void multires_get_vert(MVert *out, EditVert *eve, MVert *m, int i) -{ - if(eve) { - VecCopyf(out->co, eve->co); - out->flag= 0; - if(eve->f & SELECT) out->flag |= 1; - if(eve->h) out->flag |= ME_HIDE; - eve->tmp.l= i; + return 0; } - else - *out= *m; -} -void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease) -{ - if(!eed || !flag) return; - - /* Would be nice if EditMesh edge flags could be unified with Mesh flags! */ - *flag= (eed->f & SELECT) | ME_EDGERENDER; - if(eed->f2<2) *flag |= ME_EDGEDRAW; - if(eed->f2==0) *flag |= ME_LOOSEEDGE; - if(eed->sharp) *flag |= ME_SHARP; - if(eed->seam) *flag |= ME_SEAM; - if(eed->h & EM_FGON) *flag |= ME_FGON; - if(eed->h & 1) *flag |= ME_HIDE; - - *crease= (char)(255.0*eed->crease); + return 1; } -static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *flag, char *crease) +static void Mat3FromColVecs(float mat[][3], float v1[3], float v2[3], float v3[3]) { - if(eed) { - e->v[0]= eed->v1->tmp.l; - e->v[1]= eed->v2->tmp.l; - eed_to_medge_flag(eed, flag, crease); - } else { - e->v[0]= m->v1; - e->v[1]= m->v2; - *flag= m->flag; - *crease= m->crease; - } + VecCopyf(mat[0], v1); + VecCopyf(mat[1], v2); + VecCopyf(mat[2], v3); } -static void multires_get_face(MultiresFace *f, CustomData *fdata, int findex, EditFace *efa, MFace *m) +static DerivedMesh *multires_subdisp_pre(DerivedMesh *mrdm, int distance, int simple) { - if(efa) { - MFace tmp; - int j; - tmp.v1= efa->v1->tmp.l; - tmp.v2= efa->v2->tmp.l; - tmp.v3= efa->v3->tmp.l; - tmp.v4= 0; - if(efa->v4) tmp.v4= efa->v4->tmp.l; - test_index_face(&tmp, fdata, findex, efa->v4?4:3); - for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j]; - - /* Flags */ - f->flag= efa->flag; - if(efa->f & 1) f->flag |= ME_FACE_SEL; - else f->flag &= ~ME_FACE_SEL; - if(efa->h) f->flag |= ME_HIDE; - f->mat_nr= efa->mat_nr; - } else { - f->v[0]= m->v1; - f->v[1]= m->v2; - f->v[2]= m->v3; - f->v[3]= m->v4; - f->flag= m->flag; - f->mat_nr= m->mat_nr; - } + DerivedMesh *final; + SubsurfModifierData smd; + + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = distance; + if(simple) + smd.subdivType = ME_SIMPLE_SUBSURF; + + final = subsurf_make_derived_from_derived_with_multires(mrdm, &smd, NULL, 0, NULL, 0, 0); + + return final; } -/* For manipulating vertex colors / uvs */ -static void mcol_to_multires(MultiresColFace *mrf, MCol *mcol) +static void VecAddUf(float a[3], float b[3]) { - char i; - for(i=0; i<4; ++i) { - mrf->col[i].a= mcol[i].a; - mrf->col[i].r= mcol[i].r; - mrf->col[i].g= mcol[i].g; - mrf->col[i].b= mcol[i].b; - } + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; } -/* 1 <= count <= 4 */ -static void multires_col_avg(MultiresCol *avg, MultiresCol cols[4], char count) +static void multires_subdisp(DerivedMesh *orig, Mesh *me, DerivedMesh *final, int lvl, int totlvl, + int totsubvert, int totsubedge, int totsubface, int addverts) { - unsigned i; - avg->a= avg->r= avg->g= avg->b= 0; - for(i=0; i<count; ++i) { - avg->a+= cols[i].a; - avg->r+= cols[i].r; - avg->g+= cols[i].g; - avg->b+= cols[i].b; + DerivedMesh *mrdm; + MultiresModifierData mmd_sub; + MVert *mvs = CDDM_get_verts(final); + MVert *mvd, *mvd_f1, *mvs_f1, *mvd_f3, *mvd_f4; + MVert *mvd_f2, *mvs_f2, *mvs_e1, *mvd_e1, *mvs_e2; + int totvert; + int slo1 = multires_side_tot[lvl - 1]; + int sll = slo1 / 2; + int slo2 = multires_side_tot[totlvl - 2]; + int shi2 = multires_side_tot[totlvl - 1]; + int skip = multires_side_tot[totlvl - lvl] - 1; + int i, j, k; + + mmd_sub.lvl = mmd_sub.totlvl = totlvl; + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); + + mvd = CDDM_get_verts(mrdm); + /* Need to map from ccg to mrdm */ + totvert = mrdm->getNumVerts(mrdm); + + if(!addverts) { + for(i = 0; i < totvert; ++i) { + float z[3] = {0,0,0}; + VecCopyf(mvd[i].co, z); + } } - avg->a/= count; - avg->r/= count; - avg->g/= count; - avg->b/= count; -} -static void multires_col_avg2(MultiresCol *avg, MultiresCol *c1, MultiresCol *c2) -{ - MultiresCol in[2]; - in[0]= *c1; - in[1]= *c2; - multires_col_avg(avg,in,2); -} + /* Load base verts */ + for(i = 0; i < me->totvert; ++i) + VecAddUf(mvd[totvert - me->totvert + i].co, mvs[totvert - me->totvert + i].co); + + mvd_f1 = mvd; + mvs_f1 = mvs; + mvd_f2 = mvd; + mvs_f2 = mvs + totvert - totsubvert; + mvs_e1 = mvs + totsubface * (skip-1) * (skip-1); + + for(i = 0; i < me->totface; ++i) { + const int end = me->mface[i].v4 ? 4 : 3; + int x, y, x2, y2, mov= 0; + + mvd_f1 += 1 + end * (slo2-2); //center+edgecross + mvd_f3 = mvd_f4 = mvd_f1; + + for(j = 0; j < end; ++j) { + mvd_f1 += (skip/2 - 1) * (slo2 - 2) + (skip/2 - 1); + /* Update sub faces */ + for(y = 0; y < sll; ++y) { + for(x = 0; x < sll; ++x) { + /* Face center */ + VecAddUf(mvd_f1->co, mvs_f1->co); + mvs_f1 += 1; + + /* Now we hold the center of the subface at mvd_f1 + and offset it to the edge cross and face verts */ + + /* Edge cross */ + for(k = 0; k < 4; ++k) { + if(k == 0) mov = -1; + else if(k == 1) mov = slo2 - 2; + else if(k == 2) mov = 1; + else if(k == 3) mov = -(slo2 - 2); + + for(x2 = 1; x2 < skip/2; ++x2) { + VecAddUf((mvd_f1 + mov * x2)->co, mvs_f1->co); + ++mvs_f1; + } + } -void multires_load_cols(Mesh *me) -{ - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur; - EditMesh *em= G.obedit ? G.editMesh : NULL; - CustomData *src= em ? &em->fdata : &me->fdata; - EditFace *efa= NULL; - unsigned i,j; + /* Main face verts */ + for(k = 0; k < 4; ++k) { + int movx= 0, movy= 0; + + if(k == 0) { movx = -1; movy = -(slo2 - 2); } + else if(k == 1) { movx = slo2 - 2; movy = -1; } + else if(k == 2) { movx = 1; movy = slo2 - 2; } + else if(k == 3) { movx = -(slo2 - 2); movy = 1; } + + for(y2 = 1; y2 < skip/2; ++y2) { + for(x2 = 1; x2 < skip/2; ++x2) { + VecAddUf((mvd_f1 + movy * y2 + movx * x2)->co, mvs_f1->co); + ++mvs_f1; + } + } + } + + mvd_f1 += skip; + } + mvd_f1 += (skip - 1) * (slo2 - 2) - 1; + } + mvd_f1 -= (skip - 1) * (slo2 - 2) - 1 + skip; + mvd_f1 += (slo2 - 2) * (skip/2-1) + skip/2-1 + 1; + } - if(!CustomData_has_layer(src, CD_MCOL) && !CustomData_has_layer(src, CD_MTFACE)) return; + /* update face center verts */ + VecAddUf(mvd_f2->co, mvs_f2->co); - /* Add texcol data */ - for(cur= me->mr->levels.first; cur; cur= cur->next) - if(!cur->colfaces) - cur->colfaces= MEM_callocN(sizeof(MultiresColFace)*cur->totface,"ColFaces"); + mvd_f2 += 1; + mvs_f2 += 1; - me->mr->use_col= CustomData_has_layer(src, CD_MCOL); + /* update face edge verts */ + for(j = 0; j < end; ++j) { + MVert *restore; - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MultiresColFace *f= &lvl->colfaces[i]; + /* Super-face edge cross */ + for(k = 0; k < skip-1; ++k) { + VecAddUf(mvd_f2->co, mvs_e1->co); + mvd_f2++; + mvs_e1++; + } + for(x = 1; x < sll; ++x) { + VecAddUf(mvd_f2->co, mvs_f2->co); + mvd_f2++; + mvs_f2++; + + for(k = 0; k < skip-1; ++k) { + VecAddUf(mvd_f2->co, mvs_e1->co); + mvd_f2++; + mvs_e1++; + } + } - if(me->mr->use_col) - mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]); - - if(em) efa= efa->next; + restore = mvs_e1; + for(y = 0; y < sll - 1; ++y) { + for(x = 0; x < sll; ++x) { + for(k = 0; k < skip - 1; ++k) { + VecAddUf(mvd_f3[(skip-1)+(y*skip) + (x*skip+k)*(slo2-2)].co, + mvs_e1->co); + ++mvs_e1; + } + mvs_e1 += skip-1; + } + } + + mvs_e1 = restore + skip - 1; + for(y = 0; y < sll - 1; ++y) { + for(x = 0; x < sll; ++x) { + for(k = 0; k < skip - 1; ++k) { + VecAddUf(mvd_f3[(slo2-2)*(skip-1)+(x*skip)+k + y*skip*(slo2-2)].co, + mvs_e1->co); + ++mvs_e1; + } + mvs_e1 += skip - 1; + } + } + + mvd_f3 += (slo2-2)*(slo2-2); + mvs_e1 -= skip - 1; + } + + /* update base (2) face verts */ + for(j = 0; j < end; ++j) { + mvd_f2 += (slo2 - 1) * (skip - 1); + for(y = 0; y < sll - 1; ++y) { + for(x = 0; x < sll - 1; ++x) { + VecAddUf(mvd_f2->co, mvs_f2->co); + mvd_f2 += skip; + ++mvs_f2; + } + mvd_f2 += (slo2 - 1) * (skip - 1); + } + mvd_f2 -= (skip - 1); + } } - /* Update higher levels */ - lvl= lvl->next; - while(lvl) { - MultiresColFace *cf= lvl->colfaces; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides); + /* edges */ + mvd_e1 = mvd + totvert - me->totvert - me->totedge * (shi2-2); + mvs_e2 = mvs + totvert - me->totvert - me->totedge * (slo1-2); + for(i = 0; i < me->totedge; ++i) { + for(j = 0; j < skip - 1; ++j) { + VecAddUf(mvd_e1->co, mvs_e1->co); + mvd_e1++; + mvs_e1++; + } + for(j = 0; j < slo1 - 2; j++) { + VecAddUf(mvd_e1->co, mvs_e2->co); + mvd_e1++; + mvs_e2++; - for(j=0; j<sides; ++j) { - MultiresColFace *pf= &lvl->prev->colfaces[i]; - - multires_col_avg2(&cf->col[0], - &pf->col[j], - &pf->col[j==0?sides-1:j-1]); - cf->col[1]= pf->col[j]; - multires_col_avg2(&cf->col[2], - &pf->col[j], - &pf->col[j==sides-1?0:j+1]); - cf->col[3]= cntr; - - ++cf; + for(k = 0; k < skip - 1; ++k) { + VecAddUf(mvd_e1->co, mvs_e1->co); + mvd_e1++; + mvs_e1++; } } - lvl= lvl->next; } - /* Update lower levels */ - lvl= me->mr->levels.last; - lvl= lvl->prev; - while(lvl) { - unsigned curf= 0; - for(i=0; i<lvl->totface; ++i) { - MultiresFace *f= &lvl->faces[i]; - for(j=0; j<(f->v[3]?4:3); ++j) { - lvl->colfaces[i].col[j]= lvl->next->colfaces[curf].col[1]; - ++curf; + final->needsFree = 1; + final->release(final); + mrdm->needsFree = 1; + MultiresDM_mark_as_modified(mrdm); + mrdm->release(mrdm); +} + +/* direction=1 for delete higher, direction=0 for lower (not implemented yet) */ +void multiresModifier_del_levels(struct MultiresModifierData *mmd, struct Object *ob, int direction) +{ + Mesh *me = get_mesh(ob); + int distance = mmd->totlvl - mmd->lvl; + MDisps *mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + + multires_force_update(ob); + + if(mdisps && distance > 0 && direction == 1) { + int skip = multires_side_tot[distance] - 1; + int st = multires_side_tot[mmd->totlvl - 1]; + int totdisp = multires_quad_tot[mmd->lvl - 1]; + int i, j, x, y; + + for(i = 0; i < me->totface; ++i) { + float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires del disps"); + + for(j = 0, y = 0; y < st; y += skip) { + for(x = 0; x < st; x += skip) { + VecCopyf(disps[j], mdisps[i].disps[y * st + x]); + ++j; + } } + + MEM_freeN(mdisps[i].disps); + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; } - lvl= lvl->prev; } + + mmd->totlvl = mmd->lvl; } -void multires_create(Object *ob, Mesh *me) +void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int distance, int updateblock, int simple) { - MultiresLevel *lvl; - EditMesh *em= G.obedit ? G.editMesh : NULL; - EditVert *eve= NULL; - EditFace *efa= NULL; - EditEdge *eed= NULL; + DerivedMesh *final = NULL; + int totsubvert = 0, totsubface = 0, totsubedge = 0; + Mesh *me = get_mesh(ob); + MDisps *mdisps; int i; - - lvl= MEM_callocN(sizeof(MultiresLevel), "multires level"); - if(me->pv) mesh_pmv_off(ob, me); + if(distance == 0) + return; + + if(mmd->totlvl > multires_max_levels) + mmd->totlvl = multires_max_levels; + if(mmd->lvl > multires_max_levels) + mmd->lvl = multires_max_levels; - me->mr= MEM_callocN(sizeof(Multires), "multires data"); - - BLI_addtail(&me->mr->levels,lvl); - me->mr->current= 1; - me->mr->level_count= 1; - me->mr->edgelvl= 1; - me->mr->pinlvl= 1; - me->mr->renderlvl= 1; - - /* Load mesh (or editmesh) into multires data */ - - /* Load vertices and vdata (MDeformVerts) */ - lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert; - me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts"); - multires_update_customdata(me->mr->levels.first, em, em ? &em->vdata : &me->vdata, - &me->mr->vdata, CD_MDEFORMVERT); - if(em) eve= em->verts.first; - for(i=0; i<lvl->totvert; ++i) { - multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i); - if(em) eve= eve->next; + multires_force_update(ob); + + mmd->lvl = mmd->totlvl; + mmd->totlvl += distance; + + mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); + if(!mdisps) + mdisps = CustomData_add_layer(&me->fdata, CD_MDISPS, CD_DEFAULT, NULL, me->totface); + + if(mdisps->disps && !updateblock && mmd->totlvl > 2) { + DerivedMesh *orig, *mrdm; + MultiresModifierData mmd_sub; + + orig = CDDM_from_mesh(me, NULL); + mmd_sub.lvl = mmd_sub.totlvl = mmd->lvl; + mrdm = multires_dm_create_from_derived(&mmd_sub, orig, me, 0, 0); + totsubvert = mrdm->getNumVerts(mrdm); + totsubedge = mrdm->getNumEdges(mrdm); + totsubface = mrdm->getNumFaces(mrdm); + orig->needsFree = 1; + orig->release(orig); + + final = multires_subdisp_pre(mrdm, distance, simple); + mrdm->needsFree = 1; + mrdm->release(mrdm); } - /* Load faces and fdata (MTFaces) */ - lvl->totface= em ? BLI_countlist(&em->faces) : me->totface; - lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces"); - multires_update_customdata(me->mr->levels.first, em, em ? &em->fdata : &me->fdata, - &me->mr->fdata, CD_MTFACE); - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - multires_get_face(&lvl->faces[i], &me->mr->fdata, i, efa, &me->mface[i]); - if(em) efa= efa->next; + for(i = 0; i < me->totface; ++i) { + const int totdisp = multires_quad_tot[mmd->totlvl - 1]; + float (*disps)[3] = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disps"); + + if(mdisps[i].disps) + MEM_freeN(mdisps[i].disps); + + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; } - /* Load edges and edge_flags */ - lvl->totedge= em ? BLI_countlist(&em->edges) : me->totedge; - lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges"); - me->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge flags"); - me->mr->edge_creases= MEM_callocN(sizeof(short)*lvl->totedge, "multires edge creases"); - if(em) eed= em->edges.first; - for(i=0; i<lvl->totedge; ++i) { - multires_get_edge(&lvl->edges[i], eed, &me->medge[i], &me->mr->edge_flags[i], &me->mr->edge_creases[i]); - if(em) eed= eed->next; + + if(final) { + DerivedMesh *orig; + + orig = CDDM_from_mesh(me, NULL); + + multires_subdisp(orig, me, final, mmd->lvl, mmd->totlvl, totsubvert, totsubedge, totsubface, 0); + + orig->needsFree = 1; + orig->release(orig); } - multires_load_cols(me); + mmd->lvl = mmd->totlvl; } -typedef struct MultiresMapNode { - struct MultiresMapNode *next, *prev; - unsigned Index; -} MultiresMapNode; +typedef struct DisplacerEdges { + /* DerivedMesh index at the start of each edge (using face x/y directions to define the start) */ + int base[4]; + /* 1 if edge moves in the positive x or y direction, -1 otherwise */ + int dir[4]; +} DisplacerEdges; + +typedef struct DisplacerSpill { + /* Index of face (in base mesh), -1 for none */ + int face; + + /* Spill flag */ + /* 1 = Negative variable axis */ + /* 2 = Near fixed axis */ + /* 4 = Flip axes */ + int f; + + /* Neighboring edges */ + DisplacerEdges edges; +} DisplacerSpill; + +typedef struct MultiresDisplacer { + Mesh *me; + MDisps *grid; + MFace *face; + + int dm_first_base_vert_index; + + int spacing; + int sidetot, interior_st, disp_st; + int sidendx; + int type; + int invert; + MVert *subco; + int subco_index, face_index; + float weight; + + /* Valence for each corner */ + int valence[4]; + + /* Neighboring edges for current face */ + DisplacerEdges edges_primary; + + /* Neighboring faces */ + DisplacerSpill spill_x, spill_y; + + int *face_offsets; + + int x, y, ax, ay; +} MultiresDisplacer; -/* Produces temporary connectivity data for the multires lvl */ -static void multires_calc_temp_data(MultiresLevel *lvl) +static int mface_v(MFace *f, int v) { - unsigned i, j, emax; - MultiresMapNode *indexnode= NULL; + return v == 0 ? f->v1 : v == 1 ? f->v2 : v == 2 ? f->v3 : v == 3 ? f->v4 : -1; +} - lvl->map_mem= MEM_mallocN(sizeof(MultiresMapNode)*(lvl->totedge*2 + lvl->totface*4), "map_mem"); - indexnode= lvl->map_mem; - - /* edge map */ - lvl->vert_edge_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_edge_map"); - for(i=0; i<lvl->totedge; ++i) { - for(j=0; j<2; ++j, ++indexnode) { - indexnode->Index= i; - BLI_addtail(&lvl->vert_edge_map[lvl->edges[i].v[j]], indexnode); - } - } +/* Get the edges (and their directions) */ +static void find_displacer_edges(MultiresDisplacer *d, DerivedMesh *dm, DisplacerEdges *de, MFace *f) +{ + ListBase *emap = MultiresDM_get_vert_edge_map(dm); + IndexNode *n; + int i, end = f->v4 ? 4 : 3; + int offset = dm->getNumVerts(dm) - d->me->totvert - d->me->totedge * d->interior_st; - /* face map */ - lvl->vert_face_map= MEM_callocN(sizeof(ListBase)*lvl->totvert,"vert_face_map"); - for(i=0; i<lvl->totface; ++i){ - for(j=0; j<(lvl->faces[i].v[3]?4:3); ++j, ++indexnode) { - indexnode->Index= i; - BLI_addtail(&lvl->vert_face_map[lvl->faces[i].v[j]], indexnode); - } - } + for(i = 0; i < end; ++i) { + int vcur = mface_v(f, i); + int vnext = mface_v(f, i == end - 1 ? 0 : i + 1); - /* edge boundaries */ - emax = (lvl->prev ? (lvl->prev->totedge * 2) : lvl->totedge); - lvl->edge_boundary_states= MEM_callocN(sizeof(char)*lvl->totedge, "edge_boundary_states"); - for(i=0; i<emax; ++i) { - MultiresMapNode *n1= lvl->vert_face_map[lvl->edges[i].v[0]].first; - unsigned total= 0; + de->dir[i] = 1; - lvl->edge_boundary_states[i] = 1; - while(n1 && lvl->edge_boundary_states[i] == 1) { - MultiresMapNode *n2= lvl->vert_face_map[lvl->edges[i].v[1]].first; - while(n2) { - if(n1->Index == n2->Index) { - ++total; - - if(total > 1) { - lvl->edge_boundary_states[i] = 0; - break; - } + for(n = emap[vcur].first; n; n = n->next) { + MEdge *e = &d->me->medge[n->index]; + + if(e->v1 == vnext || e->v2 == vnext) { + de->base[i] = n->index * d->interior_st; + if(((i == 0 || i == 1) && e->v1 == vnext) || + ((i == 2 || i == 3) && e->v2 == vnext)) { + de->dir[i] = -1; + de->base[i] += d->interior_st - 1; } - - n2= n2->next; + de->base[i] += offset; + break; } - n1= n1->next; } } } -/* CATMULL-CLARK - ============= */ - -typedef struct MultiApplyData { - /* Smooth faces */ - float *corner1, *corner2, *corner3, *corner4; - char quad; - - /* Smooth edges */ - char boundary; - float edge_face_neighbor_midpoints_accum[3]; - unsigned edge_face_neighbor_midpoints_total; - float *endpoint1, *endpoint2; - - /* Smooth verts */ - /* uses 'char boundary' */ - float *original; - int edge_count; - float vert_face_neighbor_midpoints_average[3]; - float vert_edge_neighbor_midpoints_average[3]; - float boundary_edges_average[3]; -} MultiApplyData; - -/* Simply averages the four corners of a polygon. */ -static float catmullclark_smooth_face(MultiApplyData *data, const unsigned i) +/* Returns in out the corners [0-3] that use v1 and v2 */ +void find_face_corners(MFace *f, int v1, int v2, int out[2]) { - const float total= data->corner1[i]+data->corner2[i]+data->corner3[i]; - return data->quad ? (total+data->corner4[i])/4 : total/3; + int i, end = f->v4 ? 4 : 3; + + for(i = 0; i < end; ++i) { + int corner = mface_v(f, i); + if(corner == v1) + out[0] = i; + if(corner == v2) + out[1] = i; + } } -static float catmullclark_smooth_edge(MultiApplyData *data, const unsigned i) +static void multires_displacer_get_spill_faces(MultiresDisplacer *d, DerivedMesh *dm, MFace *mface) { - float accum= 0; - unsigned count= 2; - - accum+= data->endpoint1[i] + data->endpoint2[i]; + ListBase *map = MultiresDM_get_vert_face_map(dm); + IndexNode *n1, *n2; + int v4 = d->face->v4 ? d->face->v4 : d->face->v1; + int crn[2], lv; + + memset(&d->spill_x, 0, sizeof(DisplacerSpill)); + memset(&d->spill_y, 0, sizeof(DisplacerSpill)); + d->spill_x.face = d->spill_y.face = -1; + + for(n1 = map[d->face->v3].first; n1; n1 = n1->next) { + if(n1->index == d->face_index) + continue; + + for(n2 = map[d->face->v2].first; n2; n2 = n2->next) { + if(n1->index == n2->index) + d->spill_x.face = n1->index; + } + for(n2 = map[v4].first; n2; n2 = n2->next) { + if(n1->index == n2->index) + d->spill_y.face = n1->index; + } + } - if(!data->boundary) { - accum+= data->edge_face_neighbor_midpoints_accum[i]; - count+= data->edge_face_neighbor_midpoints_total; + if(d->spill_x.face != -1) { + /* Neighbor of v2/v3 found, find flip and orientation */ + find_face_corners(&mface[d->spill_x.face], d->face->v2, d->face->v3, crn); + lv = mface[d->spill_x.face].v4 ? 3 : 2; + + if(crn[0] == 0 && crn[1] == lv) + d->spill_x.f = 0+2+0; + else if(crn[0] == lv && crn[1] == 0) + d->spill_x.f = 1+2+0; + else if(crn[0] == 1 && crn[1] == 0) + d->spill_x.f = 1+2+4; + else if(crn[0] == 0 && crn[1] == 1) + d->spill_x.f = 0+2+4; + else if(crn[0] == 2 && crn[1] == 1) + d->spill_x.f = 1+0+0; + else if(crn[0] == 1 && crn[1] == 2) + d->spill_x.f = 0+0+0; + else if(crn[0] == 3 && crn[1] == 2) + d->spill_x.f = 0+0+4; + else if(crn[0] == 2 && crn[1] == 3) + d->spill_x.f = 1+0+4; + + find_displacer_edges(d, dm, &d->spill_x.edges, &mface[d->spill_x.face]); } - return accum / count; + if(d->spill_y.face != -1) { + /* Neighbor of v3/v4 found, find flip and orientation */ + find_face_corners(&mface[d->spill_y.face], d->face->v3, v4, crn); + lv = mface[d->spill_y.face].v4 ? 3 : 2; + + if(crn[0] == 1 && crn[1] == 0) + d->spill_y.f = 1+2+0; + else if(crn[0] == 0 && crn[1] == 1) + d->spill_y.f = 0+2+0; + else if(crn[0] == 2 && crn[1] == 1) + d->spill_y.f = 1+0+4; + else if(crn[0] == 1 && crn[1] == 2) + d->spill_y.f = 0+0+4; + else if(crn[0] == 3 && crn[1] == 2) + d->spill_y.f = 0+0+0; + else if(crn[0] == 2 && crn[1] == 3) + d->spill_y.f = 1+0+0; + else if(crn[0] == 0 && crn[1] == lv) + d->spill_y.f = 0+2+4; + else if(crn[0] == lv && crn[1] == 0) + d->spill_y.f = 1+2+4; + + find_displacer_edges(d, dm, &d->spill_y.edges, &mface[d->spill_y.face]); + } } -static float catmullclark_smooth_vert(MultiApplyData *data, const unsigned i) +static void find_corner_valences(MultiresDisplacer *d, DerivedMesh *dm) { - if(data->boundary) { - return data->original[i]*0.75 + data->boundary_edges_average[i]*0.25; - } else { - return (data->vert_face_neighbor_midpoints_average[i] + - 2*data->vert_edge_neighbor_midpoints_average[i] + - data->original[i]*(data->edge_count-3))/data->edge_count; - } -} + int i; + d->valence[3] = -1; + /* Set the vertex valence for the corners */ + for(i = 0; i < (d->face->v4 ? 4 : 3); ++i) + d->valence[i] = BLI_countlist(&MultiresDM_get_vert_edge_map(dm)[mface_v(d->face, i)]); +} -/* Call func count times, passing in[i] as the input and storing the output in out[i] */ -static void multi_apply(float *out, MultiApplyData *data, - const unsigned count, float (*func)(MultiApplyData *, const unsigned)) +static void multires_displacer_init(MultiresDisplacer *d, DerivedMesh *dm, + const int face_index, const int invert) { - unsigned i; - for(i=0; i<count; ++i) - out[i]= func(data,i); + Mesh *me = MultiresDM_get_mesh(dm); + + d->me = me; + d->face = me->mface + face_index; + d->face_index = face_index; + d->face_offsets = MultiresDM_get_face_offsets(dm); + /* Get the multires grid from customdata */ + d->grid = CustomData_get_layer(&me->fdata, CD_MDISPS); + if(d->grid) + d->grid += face_index; + + d->spacing = pow(2, MultiresDM_get_totlvl(dm) - MultiresDM_get_lvl(dm)); + d->sidetot = multires_side_tot[MultiresDM_get_lvl(dm) - 1]; + d->interior_st = d->sidetot - 2; + d->disp_st = multires_side_tot[MultiresDM_get_totlvl(dm) - 1]; + d->invert = invert; + + multires_displacer_get_spill_faces(d, dm, me->mface); + find_displacer_edges(d, dm, &d->edges_primary, d->face); + find_corner_valences(d, dm); + + d->dm_first_base_vert_index = dm->getNumVerts(dm) - me->totvert; } -static short multires_vert_is_boundary(MultiresLevel *lvl, unsigned v) +static void multires_displacer_weight(MultiresDisplacer *d, const float w) { - MultiresMapNode *node= lvl->vert_edge_map[v].first; - while(node) { - if(lvl->edge_boundary_states[node->Index]) - return 1; - node= node->next; - } - return 0; + d->weight = w; } -#define GET_FLOAT(array, i, j, stride) (((float*)((char*)(array)+((i)*(stride))))[(j)]) +static void multires_displacer_anchor(MultiresDisplacer *d, const int type, const int side_index) +{ + d->sidendx = side_index; + d->x = d->y = d->sidetot / 2; + d->type = type; + + if(type == 2) { + if(side_index == 0) + d->y -= 1; + else if(side_index == 1) + d->x += 1; + else if(side_index == 2) + d->y += 1; + else if(side_index == 3) + d->x -= 1; + } + else if(type == 3) { + if(side_index == 0) { + d->x -= 1; + d->y -= 1; + } + else if(side_index == 1) { + d->x += 1; + d->y -= 1; + } + else if(side_index == 2) { + d->x += 1; + d->y += 1; + } + else if(side_index == 3) { + d->x -= 1; + d->y += 1; + } + } + + d->ax = d->x; + d->ay = d->y; +} -static void edge_face_neighbor_midpoints_accum(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const MultiresEdge *e) +static void multires_displacer_anchor_edge(MultiresDisplacer *d, int v1, int v2, int x) { - ListBase *neighbors1= &lvl->vert_face_map[e->v[0]]; - ListBase *neighbors2= &lvl->vert_face_map[e->v[1]]; - MultiresMapNode *n1, *n2; - unsigned j,count= 0; - float *out= data->edge_face_neighbor_midpoints_accum; - - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors1->first; n1; n1= n1->next) { - for(n2= neighbors2->first; n2; n2= n2->next) { - if(n1->Index == n2->Index) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride); - ++count; + d->type = 4; + + if(v1 == d->face->v1) { + d->x = 0; + d->y = 0; + if(v2 == d->face->v2) + d->x += x; + else if(v2 == d->face->v3) { + if(x < d->sidetot / 2) + d->y = x; + else { + d->x = x; + d->y = d->sidetot - 1; } } + else + d->y += x; + } + else if(v1 == d->face->v2) { + d->x = d->sidetot - 1; + d->y = 0; + if(v2 == d->face->v1) + d->x -= x; + else + d->y += x; + } + else if(v1 == d->face->v3) { + d->x = d->sidetot - 1; + d->y = d->sidetot - 1; + if(v2 == d->face->v2) + d->y -= x; + else if(v2 == d->face->v1) { + if(x < d->sidetot / 2) + d->x -= x; + else { + d->x = 0; + d->y -= x; + } + } + else + d->x -= x; + } + else if(v1 == d->face->v4) { + d->x = 0; + d->y = d->sidetot - 1; + if(v2 == d->face->v3) + d->x += x; + else + d->y -= x; } - - data->edge_face_neighbor_midpoints_total= count; } -static void vert_face_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +static void multires_displacer_anchor_vert(MultiresDisplacer *d, const int v) { - ListBase *neighbors= &lvl->vert_face_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->vert_face_neighbor_midpoints_average; + const int e = d->sidetot - 1; - out[0]=out[1]=out[2]= 0; + d->type = 5; - for(n1= neighbors->first; n1; n1= n1->next) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,lvl->faces[n1->Index].mid,j,stride); - ++count; - } - for(j=0; j<3; ++j) out[j]/= count; + d->x = d->y = 0; + if(v == d->face->v2) + d->x = e; + else if(v == d->face->v3) + d->x = d->y = e; + else if(v == d->face->v4) + d->y = e; } -static void vert_edge_neighbor_midpoints_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +static void multires_displacer_jump(MultiresDisplacer *d) { - ListBase *neighbors= &lvl->vert_edge_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->vert_edge_neighbor_midpoints_average; - - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors->first; n1; n1= n1->next) { - for(j=0; j<3; ++j) - out[j]+= (GET_FLOAT(array,lvl->edges[n1->Index].v[0],j,stride) + - GET_FLOAT(array,lvl->edges[n1->Index].v[1],j,stride)) / 2; - ++count; + if(d->sidendx == 0) { + d->x -= 1; + d->y = d->ay; + } + else if(d->sidendx == 1) { + d->x = d->ax; + d->y -= 1; + } + else if(d->sidendx == 2) { + d->x += 1; + d->y = d->ay; + } + else if(d->sidendx == 3) { + d->x = d->ax; + d->y += 1; } - for(j=0; j<3; ++j) out[j]/= count; } -static void boundary_edges_average(MultiApplyData *data, MultiresLevel *lvl, - void *array, const char stride, const unsigned i) +/* Treating v1 as (0,0) and v3 as (st-1,st-1), + returns the index of the vertex at (x,y). + If x or y is >= st, wraps over to the adjacent face, + or if there is no adjacent face, returns -2. */ +static int multires_index_at_loc(int face_index, int x, int y, MultiresDisplacer *d, DisplacerEdges *de) { - ListBase *neighbors= &lvl->vert_edge_map[i]; - MultiresMapNode *n1; - unsigned j,count= 0; - float *out= data->boundary_edges_average; + int coord_edge = d->sidetot - 1; /* Max value of x/y at edge of grid */ + int mid = d->sidetot / 2; + int lim = mid - 1; + int qtot = lim * lim; + int base = d->face_offsets[face_index]; + + /* Edge spillover */ + if(x == d->sidetot || y == d->sidetot) { + int flags, v_axis, f_axis, lx, ly; + + if(x == d->sidetot && d->spill_x.face != -1) { + flags = d->spill_x.f; + + /* Handle triangle seam between v1 and v3 */ + if(!d->me->mface[d->spill_x.face].v4 && + ((flags == 2 && y >= mid) || (flags == 3 && y < mid))) + flags += 2; + + v_axis = (flags & 1) ? d->sidetot - 1 - y : y; + f_axis = (flags & 2) ? 1 : d->sidetot - 2; + lx = f_axis, ly = v_axis; + + if(flags & 4) { + lx = v_axis; + ly = f_axis; + } - out[0]=out[1]=out[2]= 0; - - for(n1= neighbors->first; n1; n1= n1->next) { - const MultiresEdge *e= &lvl->edges[n1->Index]; - const unsigned end= e->v[0]==i ? e->v[1] : e->v[0]; - - if(lvl->edge_boundary_states[n1->Index]) { - for(j=0; j<3; ++j) - out[j]+= GET_FLOAT(array,end,j,stride); - ++count; + return multires_index_at_loc(d->spill_x.face, lx, ly, d, &d->spill_x.edges); + } + else if(y == d->sidetot && d->spill_y.face != -1) { + flags = d->spill_y.f; + + /* Handle triangle seam between v1 and v3 */ + if(!d->me->mface[d->spill_y.face].v4 && + ((flags == 6 && x >= mid) || (flags == 7 && x < mid))) + flags = ~flags; + + v_axis = (flags & 1) ? x : d->sidetot - 1 - x; + f_axis = (flags & 2) ? 1 : d->sidetot - 2; + lx = v_axis, ly = f_axis; + + if(flags & 4) { + lx = f_axis; + ly = v_axis; + } + + return multires_index_at_loc(d->spill_y.face, lx, ly, d, &d->spill_y.edges); } + else + return -2; + } + /* Corners */ + else if(x == 0 && y == 0) + return d->dm_first_base_vert_index + d->face->v1; + else if(x == coord_edge && y == 0) + return d->dm_first_base_vert_index + d->face->v2; + else if(x == coord_edge && y == coord_edge) + return d->dm_first_base_vert_index + d->face->v3; + else if(x == 0 && y == coord_edge) + return d->dm_first_base_vert_index + d->face->v4; + /* Edges */ + else if(x == 0) { + if(d->face->v4) + return de->base[3] + de->dir[3] * (y - 1); + else + return de->base[2] + de->dir[2] * (y - 1); + } + else if(y == 0) + return de->base[0] + de->dir[0] * (x - 1); + else if(x == d->sidetot - 1) + return de->base[1] + de->dir[1] * (y - 1); + else if(y == d->sidetot - 1) + return de->base[2] + de->dir[2] * (x - 1); + /* Face center */ + else if(x == mid && y == mid) + return base; + /* Cross */ + else if(x == mid && y < mid) + return base + (mid - y); + else if(y == mid && x > mid) + return base + lim + (x - mid); + else if(x == mid && y > mid) + return base + lim*2 + (y - mid); + else if(y == mid && x < mid) { + if(d->face->v4) + return base + lim*3 + (mid - x); + else + return base + lim*2 + (mid - x); + } + /* Quarters */ + else { + int offset = base + lim * (d->face->v4 ? 4 : 3); + if(x < mid && y < mid) + return offset + ((mid - x - 1)*lim + (mid - y)); + else if(x > mid && y < mid) + return offset + qtot + ((mid - y - 1)*lim + (x - mid)); + else if(x > mid && y > mid) + return offset + qtot*2 + ((x - mid - 1)*lim + (y - mid)); + else if(x < mid && y > mid) + return offset + qtot*3 + ((y - mid - 1)*lim + (mid - x)); } - for(j=0; j<3; ++j) out[j]/= count; + + return -1; } -/* END CATMULL-CLARK - ================= */ - -/* Update vertex locations and vertex flags */ -static void multires_update_vertices(Mesh *me, EditMesh *em) +/* Calculate the TS matrix used for applying displacements. + Uses the undisplaced subdivided mesh's curvature to find a + smoothly normal and tangents. */ +static void calc_disp_mat(MultiresDisplacer *d, float mat[3][3]) { - MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL, - *last_lvl= me->mr->levels.last; - vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL; - EditVert *eve= NULL; - MultiApplyData data; - int i, j; - - /* XXX added this to prevent crash, but if it works? (ton) */ - if(me->mr->verts==NULL) - return; + int u = multires_index_at_loc(d->face_index, d->x + 1, d->y, d, &d->edges_primary); + int v = multires_index_at_loc(d->face_index, d->x, d->y + 1, d, &d->edges_primary); + float norm[3], t1[3], t2[3], inv[3][3]; + MVert *base = d->subco + d->subco_index; + + //printf("f=%d, x=%d, y=%d, i=%d, u=%d, v=%d ", d->face_index, d->x, d->y, d->subco_index, u, v); - /* Prepare deltas */ - pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1"); - cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2"); - - /* Calculate initial deltas -- current mesh subtracted from current level*/ - if(em) eve= em->verts.first; - for(i=0; i<cr_lvl->totvert; ++i) { - if(em) { - VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co); - eve= eve->next; - } else - VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co); + norm[0] = base->no[0] / 32767.0f; + norm[1] = base->no[1] / 32767.0f; + norm[2] = base->no[2] / 32767.0f; + + /* Special handling for vertices of valence 3 */ + if(d->valence[1] == 3 && d->x == d->sidetot - 1 && d->y == 0) + u = -1; + else if(d->valence[2] == 3 && d->x == d->sidetot - 1 && d->y == d->sidetot - 1) + u = v = -1; + else if(d->valence[3] == 3 && d->x == 0 && d->y == d->sidetot - 1) + v = -1; + + /* If either u or v is -2, it's on a boundary. In this + case, back up by one row/column and use the same + vector as the preceeding sub-edge. */ + + if(u < 0) { + u = multires_index_at_loc(d->face_index, d->x - 1, d->y, d, &d->edges_primary); + VecSubf(t1, base->co, d->subco[u].co); } + else + VecSubf(t1, d->subco[u].co, base->co); - - /* Copy current level's vertex flags and clear the rest */ - if(em) eve= em->verts.first; - for(i=0; i < last_lvl->totvert; ++i) { - if(i < cr_lvl->totvert) { - MVert mvflag; - multires_get_vert(&mvflag, eve, &me->mvert[i], i); - if(em) eve= eve->next; - me->mr->verts[i].flag= mvflag.flag; - } - else - me->mr->verts[i].flag= 0; + if(v < 0) { + v = multires_index_at_loc(d->face_index, d->x, d->y - 1, d, &d->edges_primary); + VecSubf(t2, base->co, d->subco[v].co); } + else + VecSubf(t2, d->subco[v].co, base->co); - /* If already on the highest level, copy current verts (including flags) into current level */ - if(cr_lvl == last_lvl) { - if(em) - eve= em->verts.first; - for(i=0; i<cr_lvl->totvert; ++i) { - multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i); - if(em) eve= eve->next; - } + //printf("uu=%d, vv=%d\n", u, v); + + Normalize(t1); + Normalize(t2); + Mat3FromColVecs(mat, t1, t2, norm); + + if(d->invert) { + Mat3Inv(inv, mat); + Mat3CpyMat3(mat, inv); } +} - /* Update higher levels */ - pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - cr_lvl= pr_lvl->next; - while(cr_lvl) { - multires_calc_temp_data(pr_lvl); - - /* Swap the old/new deltas */ - swap_deltas= pr_deltas; - pr_deltas= cr_deltas; - cr_deltas= swap_deltas; - - /* Calculate and add new deltas - ============================ */ - for(i=0; i<pr_lvl->totface; ++i) { - const MultiresFace *f= &pr_lvl->faces[i]; - data.corner1= &pr_deltas[f->v[0]].x; - data.corner2= &pr_deltas[f->v[1]].x; - data.corner3= &pr_deltas[f->v[2]].x; - data.corner4= &pr_deltas[f->v[3]].x; - data.quad= f->v[3] ? 1 : 0; - multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face); - - for(j=0; j<(data.quad?4:3); ++j) - me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag; - } +static void multires_displace(MultiresDisplacer *d, float co[3]) +{ + float disp[3], mat[3][3]; + float *data; + MVert *subco = &d->subco[d->subco_index]; - for(i=0; i<pr_lvl->totedge; ++i) { - const MultiresEdge *e= &pr_lvl->edges[i]; - data.boundary= pr_lvl->edge_boundary_states[i]; - edge_face_neighbor_midpoints_accum(&data,pr_lvl,cr_deltas,sizeof(vec3f),e); - data.endpoint1= &pr_deltas[e->v[0]].x; - data.endpoint2= &pr_deltas[e->v[1]].x; - multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge); - - for(j=0; j<2; ++j) - me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag; - } + if(!d->grid || !d->grid->disps) return; - for(i=0; i<pr_lvl->totvert; ++i) { - data.boundary= multires_vert_is_boundary(pr_lvl,i); - data.original= &pr_deltas[i].x; - data.edge_count= BLI_countlist(&pr_lvl->vert_edge_map[i]); - if(data.boundary) - boundary_edges_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i); - else { - vert_face_neighbor_midpoints_average(&data,pr_lvl,cr_deltas,sizeof(vec3f),i); - vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i); - } - multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert); - } + data = d->grid->disps[(d->y * d->spacing) * d->disp_st + (d->x * d->spacing)]; + + if(d->invert) + VecSubf(disp, co, subco->co); + else + VecCopyf(disp, data); - /* Apply deltas to vertex locations */ - for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) { - VecAddf(me->mr->verts[i].co, - me->mr->verts[i].co, - &cr_deltas[i].x); - } - multires_free_temp_data(pr_lvl); + /* Apply ts matrix to displacement */ + calc_disp_mat(d, mat); + Mat3MulVecfl(mat, disp); - pr_lvl= pr_lvl->next; - cr_lvl= cr_lvl->next; + if(d->invert) { + VecCopyf(data, disp); + + } + else { + if(d->type == 4 || d->type == 5) + VecMulf(disp, d->weight); + VecAddf(co, co, disp); } - if(pr_deltas) MEM_freeN(pr_deltas); - if(cr_deltas) MEM_freeN(cr_deltas); + if(d->type == 2) { + if(d->sidendx == 0) + d->y -= 1; + else if(d->sidendx == 1) + d->x += 1; + else if(d->sidendx == 2) + d->y += 1; + else if(d->sidendx == 3) + d->x -= 1; + } + else if(d->type == 3) { + if(d->sidendx == 0) + d->y -= 1; + else if(d->sidendx == 1) + d->x += 1; + else if(d->sidendx == 2) + d->y += 1; + else if(d->sidendx == 3) + d->x -= 1; + } } -static void multires_update_faces(Mesh *me, EditMesh *em) +static void multiresModifier_disp_run(DerivedMesh *dm, MVert *subco, int invert) { - MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL, - *last_lvl= me->mr->levels.last; - char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL, - *pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL; - EditFace *efa= NULL; - unsigned i,j,curf; - - /* Find for each face whether flag/mat has changed */ - pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1"); - cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1"); - pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1"); - cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1"); - if(em) efa= em->faces.first; - for(i=0; i<cr_lvl->totface; ++i) { - MultiresFace mftmp; - multires_get_face(&mftmp, &me->mr->fdata, i, efa, &me->mface[i]); - if(cr_lvl->faces[i].flag != mftmp.flag) - cr_flag_damaged[i]= 1; - if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr) - cr_mat_damaged[i]= 1; - - /* Update current level */ - cr_lvl->faces[i].flag= mftmp.flag; - cr_lvl->faces[i].mat_nr= mftmp.mat_nr; - - if(em) efa= efa->next; - } - or_flag_damaged= MEM_dupallocN(cr_flag_damaged); - or_mat_damaged= MEM_dupallocN(cr_mat_damaged); - - /* Update lower levels */ - cr_lvl= cr_lvl->prev; - while(cr_lvl) { - swap= pr_flag_damaged; - pr_flag_damaged= cr_flag_damaged; - cr_flag_damaged= swap; - - swap= pr_mat_damaged; - pr_mat_damaged= cr_mat_damaged; - cr_mat_damaged= swap; - - curf= 0; - for(i=0; i<cr_lvl->totface; ++i) { - const int sides= cr_lvl->faces[i].v[3] ? 4 : 3; - - /* Check damages */ - for(j=0; j<sides; ++j, ++curf) { - if(pr_flag_damaged[curf]) { - cr_lvl->faces[i].flag= cr_lvl->next->faces[curf].flag; - cr_flag_damaged[i]= 1; - } - if(pr_mat_damaged[curf]) { - cr_lvl->faces[i].mat_nr= cr_lvl->next->faces[curf].mat_nr; - cr_mat_damaged[i]= 1; - } + const int lvl = MultiresDM_get_lvl(dm); + const int gridFaces = multires_side_tot[lvl - 2] - 1; + const int edgeSize = multires_side_tot[lvl - 1] - 1; + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = MultiresDM_get_mesh(dm)->medge; + MFace *mface = MultiresDM_get_mesh(dm)->mface; + ListBase *map = MultiresDM_get_vert_face_map(dm); + Mesh *me = MultiresDM_get_mesh(dm); + MultiresDisplacer d; + int i, S, x, y; + + d.subco = subco; + d.subco_index = 0; + + for(i = 0; i < me->totface; ++i) { + const int numVerts = mface[i].v4 ? 4 : 3; + + /* Center */ + multires_displacer_init(&d, dm, i, invert); + multires_displacer_anchor(&d, 1, 0); + multires_displace(&d, mvert->co); + ++mvert; + ++d.subco_index; + + /* Cross */ + for(S = 0; S < numVerts; ++S) { + multires_displacer_anchor(&d, 2, S); + for(x = 1; x < gridFaces; ++x) { + multires_displace(&d, mvert->co); + ++mvert; + ++d.subco_index; } } - cr_lvl= cr_lvl->prev; - } - - /* Clear to original damages */ - if(cr_flag_damaged) MEM_freeN(cr_flag_damaged); - if(cr_mat_damaged) MEM_freeN(cr_mat_damaged); - cr_flag_damaged= or_flag_damaged; - cr_mat_damaged= or_mat_damaged; - - /* Update higher levels */ - pr_lvl= current_level(me->mr); - cr_lvl= pr_lvl->next; - while(cr_lvl) { - swap= pr_flag_damaged; - pr_flag_damaged= cr_flag_damaged; - cr_flag_damaged= swap; - - swap= pr_mat_damaged; - pr_mat_damaged= cr_mat_damaged; - cr_mat_damaged= swap; - - /* Update faces */ - for(i=0, curf= 0; i<pr_lvl->totface; ++i) { - const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; - for(j=0; j<sides; ++j, ++curf) { - if(pr_flag_damaged[i]) { - cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag; - cr_flag_damaged[curf]= 1; - } - if(pr_mat_damaged[i]) { - cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr; - cr_mat_damaged[curf]= 1; + /* Quarters */ + for(S = 0; S < numVerts; S++) { + multires_displacer_anchor(&d, 3, S); + for(y = 1; y < gridFaces; y++) { + for(x = 1; x < gridFaces; x++) { + multires_displace(&d, mvert->co); + ++mvert; + ++d.subco_index; } + multires_displacer_jump(&d); } } - - pr_lvl= pr_lvl->next; - cr_lvl= cr_lvl->next; } - if(pr_flag_damaged) MEM_freeN(pr_flag_damaged); - if(cr_flag_damaged) MEM_freeN(cr_flag_damaged); - if(pr_mat_damaged) MEM_freeN(pr_mat_damaged); - if(cr_mat_damaged) MEM_freeN(cr_mat_damaged); -} - -static void multires_update_colors(Mesh *me, EditMesh *em) -{ - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - MultiresCol *pr_deltas= NULL, *cr_deltas= NULL; - CustomData *src= em ? &em->fdata : &me->fdata; - EditFace *efa= NULL; - unsigned i,j,curf= 0; - - if(me->mr->use_col) { - /* Calc initial deltas */ - cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"initial color/uv deltas"); - - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MCol *col= em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]; - for(j=0; j<4; ++j) { - if(me->mr->use_col) { - cr_deltas[i*4+j].a= col[j].a - lvl->colfaces[i].col[j].a; - cr_deltas[i*4+j].r= col[j].r - lvl->colfaces[i].col[j].r; - cr_deltas[i*4+j].g= col[j].g - lvl->colfaces[i].col[j].g; - cr_deltas[i*4+j].b= col[j].b - lvl->colfaces[i].col[j].b; - } - } - if(em) efa= efa->next; - } - - /* Update current level */ - if(em) efa= em->faces.first; - for(i=0; i<lvl->totface; ++i) { - MultiresColFace *f= &lvl->colfaces[i]; - - if(me->mr->use_col) - mcol_to_multires(f, em ? CustomData_em_get(src, efa->data, CD_MCOL) : &me->mcol[i*4]); - - if(em) efa= efa->next; - } - - /* Update higher levels */ - lvl= lvl->next; - while(lvl) { - /* Set up new deltas, but keep the ones from the previous level */ - if(pr_deltas) MEM_freeN(pr_deltas); - pr_deltas= cr_deltas; - cr_deltas= MEM_callocN(sizeof(MultiresCol)*lvl->totface*4,"color deltas"); - - curf= 0; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,&pr_deltas[i*4],sides); - - for(j=0; j<sides; ++j) { - multires_col_avg2(&cr_deltas[curf*4], - &pr_deltas[i*4+j], - &pr_deltas[i*4+(j==0?sides-1:j-1)]); - cr_deltas[curf*4+1]= pr_deltas[i*4+j]; - multires_col_avg2(&cr_deltas[curf*4+2], - &pr_deltas[i*4+j], - &pr_deltas[i*4+(j==sides-1?0:j+1)]); - cr_deltas[curf*4+3]= cntr; - ++curf; + for(i = 0; i < me->totedge; ++i) { + const MEdge *e = &medge[i]; + for(x = 1; x < edgeSize; ++x) { + IndexNode *n1, *n2; + int numFaces = 0; + for(n1 = map[e->v1].first; n1; n1 = n1->next) { + for(n2 = map[e->v2].first; n2; n2 = n2->next) { + if(n1->index == n2->index) + ++numFaces; } } - - for(i=0; i<lvl->totface; ++i) { - for(j=0; j<4; ++j) { - lvl->colfaces[i].col[j].a+= cr_deltas[i*4+j].a; - lvl->colfaces[i].col[j].r+= cr_deltas[i*4+j].r; - lvl->colfaces[i].col[j].g+= cr_deltas[i*4+j].g; - lvl->colfaces[i].col[j].b+= cr_deltas[i*4+j].b; + multires_displacer_weight(&d, 1.0f / numFaces); + /* TODO: Better to have these loops outside the x loop */ + for(n1 = map[e->v1].first; n1; n1 = n1->next) { + for(n2 = map[e->v2].first; n2; n2 = n2->next) { + if(n1->index == n2->index) { + multires_displacer_init(&d, dm, n1->index, invert); + multires_displacer_anchor_edge(&d, e->v1, e->v2, x); + multires_displace(&d, mvert->co); + } } } - - lvl= lvl->next; + ++mvert; + ++d.subco_index; } - if(pr_deltas) MEM_freeN(pr_deltas); - if(cr_deltas) MEM_freeN(cr_deltas); + } - /* Update lower levels */ - lvl= me->mr->levels.last; - lvl= lvl->prev; - while(lvl) { - MultiresColFace *nf= lvl->next->colfaces; - for(i=0; i<lvl->totface; ++i) { - MultiresFace *f= &lvl->faces[i]; - for(j=0; j<(f->v[3]?4:3); ++j) { - lvl->colfaces[i].col[j]= nf->col[1]; - ++nf; - } - } - lvl= lvl->prev; + for(i = 0; i < me->totvert; ++i) { + IndexNode *n; + multires_displacer_weight(&d, 1.0f / BLI_countlist(&map[i])); + for(n = map[i].first; n; n = n->next) { + multires_displacer_init(&d, dm, n->index, invert); + multires_displacer_anchor_vert(&d, i); + multires_displace(&d, mvert->co); } + ++mvert; + ++d.subco_index; } + + if(!invert) + CDDM_calc_normals(dm); } -void multires_update_levels(Mesh *me, const int render) +static void multiresModifier_update(DerivedMesh *dm) { - EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL; + Mesh *me; + MDisps *mdisps; - multires_update_first_level(me, em); - multires_update_vertices(me, em); - multires_update_faces(me, em); - multires_update_colors(me, em); -} + me = MultiresDM_get_mesh(dm); + mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS); -static void check_colors(Mesh *me) -{ - CustomData *src= G.obedit ? &G.editMesh->fdata : &me->fdata; - const char col= CustomData_has_layer(src, CD_MCOL); - - /* Check if vertex colors have been deleted or added */ - if(me->mr->use_col && !col) - me->mr->use_col= 0; - else if(!me->mr->use_col && col) { - me->mr->use_col= 1; - multires_load_cols(me); - } -} + if(mdisps) { + const int lvl = MultiresDM_get_lvl(dm); + const int totlvl = MultiresDM_get_totlvl(dm); + + if(lvl < totlvl) { + /* Propagate disps upwards */ + DerivedMesh *final, *subco_dm, *orig; + MVert *verts_new = NULL, *cur_lvl_orig_verts = NULL; + MultiresModifierData mmd; + int i; + + orig = CDDM_from_mesh(me, NULL); + + /* Regenerate the current level's vertex coordinates + (includes older displacements but not new sculpts) */ + mmd.totlvl = totlvl; + mmd.lvl = lvl; + subco_dm = multires_dm_create_from_derived(&mmd, orig, me, 0, 0); + cur_lvl_orig_verts = CDDM_get_verts(subco_dm); -static unsigned int find_mid_edge(ListBase *vert_edge_map, - MultiresLevel *lvl, - const unsigned int v1, - const unsigned int v2 ) -{ - MultiresMapNode *n= vert_edge_map[v1].first; - while(n) { - if(lvl->edges[n->Index].v[0]==v2 || - lvl->edges[n->Index].v[1]==v2) - return lvl->edges[n->Index].mid; + /* Subtract the original vertex cos from the new vertex cos */ + verts_new = CDDM_get_verts(dm); + for(i = 0; i < dm->getNumVerts(dm); ++i) + VecSubf(verts_new[i].co, verts_new[i].co, cur_lvl_orig_verts[i].co); + + final = multires_subdisp_pre(dm, totlvl - lvl, 0); + + multires_subdisp(orig, me, final, lvl, totlvl, dm->getNumVerts(dm), dm->getNumEdges(dm), + dm->getNumFaces(dm), 1); - n= n->next; + subco_dm->release(subco_dm); + orig->release(orig); + } + else + multiresModifier_disp_run(dm, MultiresDM_get_subco(dm), 1); } - return -1; } -static float clamp_component(const float c) +void multires_mark_as_modified(struct Object *ob) { - if(c<0) return 0; - else if(c>255) return 255; - else return c; + if(ob && ob->derivedFinal) { + MultiresDM_mark_as_modified(ob->derivedFinal); + } } -void multires_to_mcol(MultiresColFace *f, MCol mcol[4]) +void multires_force_update(Object *ob) { - unsigned char j; - for(j=0; j<4; ++j) { - mcol->a= clamp_component(f->col[j].a); - mcol->r= clamp_component(f->col[j].r); - mcol->g= clamp_component(f->col[j].g); - mcol->b= clamp_component(f->col[j].b); - ++mcol; + if(ob && ob->derivedFinal) { + ob->derivedFinal->needsFree =1; + ob->derivedFinal->release(ob->derivedFinal); + ob->derivedFinal = NULL; } } -void multires_level_to_mesh(Object *ob, Mesh *me, const int render) +struct DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, DerivedMesh *dm, Mesh *me, + int useRenderParams, int isFinalCalc) { - MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); + SubsurfModifierData smd; + MultiresSubsurf ms; + DerivedMesh *result; int i; - EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL; - - if(em) - return; - CustomData_free_layer_active(&me->vdata, CD_MVERT, me->totvert); - CustomData_free_layer_active(&me->edata, CD_MEDGE, me->totedge); - CustomData_free_layer_active(&me->fdata, CD_MFACE, me->totface); - CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); - CustomData_free_layers(&me->fdata, CD_MTFACE, me->totface); - CustomData_free_layers(&me->fdata, CD_MCOL, me->totface); - - me->totvert= lvl->totvert; - me->totface= lvl->totface; - me->totedge= lvl->totedge; + ms.mmd = mmd; + ms.me = me; - CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge); - CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface); - mesh_update_customdata_pointers(me); + memset(&smd, 0, sizeof(SubsurfModifierData)); + smd.levels = smd.renderLevels = mmd->lvl - 1; + smd.flags |= eSubsurfModifierFlag_SubsurfUv; - /* Vertices/Edges/Faces */ - - for(i=0; i<lvl->totvert; ++i) { - me->mvert[i]= me->mr->verts[i]; - } - for(i=0; i<lvl->totedge; ++i) { - me->medge[i].v1= lvl->edges[i].v[0]; - me->medge[i].v2= lvl->edges[i].v[1]; - me->medge[i].flag &= ~ME_HIDE; - } - for(i=0; i<lvl->totface; ++i) { - me->mface[i].v1= lvl->faces[i].v[0]; - me->mface[i].v2= lvl->faces[i].v[1]; - me->mface[i].v3= lvl->faces[i].v[2]; - me->mface[i].v4= lvl->faces[i].v[3]; - me->mface[i].flag= lvl->faces[i].flag; - me->mface[i].flag &= ~ME_HIDE; - me->mface[i].mat_nr= lvl->faces[i].mat_nr; + result = subsurf_make_derived_from_derived_with_multires(dm, &smd, &ms, useRenderParams, NULL, isFinalCalc, 0); + for(i = 0; i < result->getNumVerts(result); ++i) + MultiresDM_get_subco(result)[i] = CDDM_get_verts(result)[i]; + multiresModifier_disp_run(result, MultiresDM_get_subco(result), 0); + MultiresDM_set_update(result, multiresModifier_update); + + return result; +} + +/**** Old Multires code **** +***************************/ + +/* Does not actually free lvl itself */ +void multires_free_level(MultiresLevel *lvl) +{ + if(lvl) { + if(lvl->faces) MEM_freeN(lvl->faces); + if(lvl->edges) MEM_freeN(lvl->edges); + if(lvl->colfaces) MEM_freeN(lvl->colfaces); } - - /* Edge flags */ - if(lvl==me->mr->levels.first) { - for(i=0; i<lvl->totedge; ++i) { - me->medge[i].flag= me->mr->edge_flags[i]; - me->medge[i].crease= me->mr->edge_creases[i]; +} + +void multires_free(Multires *mr) +{ + if(mr) { + MultiresLevel* lvl= mr->levels.first; + + /* Free the first-level data */ + if(lvl) { + CustomData_free(&mr->vdata, lvl->totvert); + CustomData_free(&mr->fdata, lvl->totface); + MEM_freeN(mr->edge_flags); + MEM_freeN(mr->edge_creases); } - } else { - MultiresLevel *lvl1= me->mr->levels.first; - const int last= lvl1->totedge * pow(2, me->mr->current-1); - for(i=0; i<last; ++i) { - const int ndx= i / pow(2, me->mr->current-1); - - me->medge[i].flag= me->mr->edge_flags[ndx]; - me->medge[i].crease= me->mr->edge_creases[ndx]; + + while(lvl) { + multires_free_level(lvl); + lvl= lvl->next; } - } - multires_customdata_to_mesh(me, em, lvl, &me->mr->vdata, em ? &em->vdata : &me->vdata, CD_MDEFORMVERT); - multires_customdata_to_mesh(me, em, lvl, &me->mr->fdata, em ? &em->fdata : &me->fdata, CD_MTFACE); + MEM_freeN(mr->verts); - /* Colors */ - if(me->mr->use_col) { - CustomData *src= &me->fdata; - - if(me->mr->use_col) me->mcol= CustomData_add_layer(src, CD_MCOL, CD_CALLOC, NULL, me->totface); - - for(i=0; i<lvl->totface; ++i) { - if(me->mr->use_col) - multires_to_mcol(&lvl->colfaces[i], &me->mcol[i*4]); - } - + BLI_freelistN(&mr->levels); + + MEM_freeN(mr); } +} + +static void create_old_vert_face_map(ListBase **map, IndexNode **mem, const MultiresFace *mface, + const int totvert, const int totface) +{ + int i,j; + IndexNode *node = NULL; - mesh_update_customdata_pointers(me); + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert face map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totface*4, "vert face map mem"); + node = *mem; - multires_edge_level_update(ob,me); - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); + /* Find the users */ + for(i = 0; i < totface; ++i){ + for(j = 0; j < (mface[i].v[3]?4:3); ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[mface[i].v[j]], node); + } + } } -void multires_add_level(Object *ob, Mesh *me, const char subdiv_type) +static void create_old_vert_edge_map(ListBase **map, IndexNode **mem, const MultiresEdge *medge, + const int totvert, const int totedge) { - int i,j, curf, cure; - MultiresLevel *lvl= NULL; - MultiApplyData data; - MVert *oldverts= NULL; + int i,j; + IndexNode *node = NULL; + + (*map) = MEM_callocN(sizeof(ListBase) * totvert, "vert edge map"); + (*mem) = MEM_callocN(sizeof(IndexNode) * totedge*2, "vert edge map mem"); + node = *mem; - lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel"); - if(me->pv) mesh_pmv_off(ob, me); - - check_colors(me); - multires_update_levels(me, 0); - - ++me->mr->level_count; - BLI_addtail(&me->mr->levels,lvl); - - /* Create vertices - =============== */ - lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface; - oldverts= me->mr->verts; - me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts"); - /* Copy old verts */ - for(i=0; i<lvl->prev->totvert; ++i) - me->mr->verts[i]= oldverts[i]; - /* Create new edge verts */ - for(i=0; i<lvl->prev->totedge; ++i) { - VecMidf(me->mr->verts[lvl->prev->totvert + i].co, - oldverts[lvl->prev->edges[i].v[0]].co, - oldverts[lvl->prev->edges[i].v[1]].co); - lvl->prev->edges[i].mid= lvl->prev->totvert + i; + /* Find the users */ + for(i = 0; i < totedge; ++i){ + for(j = 0; j < 2; ++j, ++node) { + node->index = i; + BLI_addtail(&(*map)[medge[i].v[j]], node); + } } - /* Create new face verts */ - for(i=0; i<lvl->prev->totface; ++i) { - lvl->prev->faces[i].mid= lvl->prev->totvert + lvl->prev->totedge + i; +} + +static MultiresFace *find_old_face(ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4) +{ + IndexNode *n1; + int v[4] = {v1, v2, v3, v4}, i, j; + + for(n1 = map[v1].first; n1; n1 = n1->next) { + int fnd[4] = {0, 0, 0, 0}; + + for(i = 0; i < 4; ++i) { + for(j = 0; j < 4; ++j) { + if(v[i] == faces[n1->index].v[j]) + fnd[i] = 1; + } + } + + if(fnd[0] && fnd[1] && fnd[2] && fnd[3]) + return &faces[n1->index]; } - multires_calc_temp_data(lvl->prev); + return NULL; +} - /* Create faces - ============ */ - /* Allocate all the new faces (each triangle creates three, and - each quad creates four */ - lvl->totface= 0; - for(i=0; i<lvl->prev->totface; ++i) - lvl->totface+= lvl->prev->faces[i].v[3] ? 4 : 3; - lvl->faces= MEM_callocN(sizeof(MultiresFace)*lvl->totface,"multires faces"); +static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2) +{ + IndexNode *n1, *n2; - curf= 0; - for(i=0; i<lvl->prev->totface; ++i) { - const int max= lvl->prev->faces[i].v[3] ? 3 : 2; - - for(j=0; j<max+1; ++j) { - lvl->faces[curf].v[0]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev, - lvl->prev->faces[i].v[j], - lvl->prev->faces[i].v[j==0?max:j-1]); - lvl->faces[curf].v[1]= lvl->prev->faces[i].v[j]; - lvl->faces[curf].v[2]= find_mid_edge(lvl->prev->vert_edge_map,lvl->prev, - lvl->prev->faces[i].v[j], - lvl->prev->faces[i].v[j==max?0:j+1]); - lvl->faces[curf].v[3]= lvl->prev->totvert + lvl->prev->totedge + i; - lvl->faces[curf].flag= lvl->prev->faces[i].flag; - lvl->faces[curf].mat_nr= lvl->prev->faces[i].mat_nr; - - ++curf; + for(n1 = map[v1].first; n1; n1 = n1->next) { + for(n2 = map[v2].first; n2; n2 = n2->next) { + if(n1->index == n2->index) + return &edges[n1->index]; } } - /* Create edges - ============ */ - /* Figure out how many edges to allocate */ - lvl->totedge= lvl->prev->totedge*2; - for(i=0; i<lvl->prev->totface; ++i) - lvl->totedge+= lvl->prev->faces[i].v[3]?4:3; - lvl->edges= MEM_callocN(sizeof(MultiresEdge)*lvl->totedge,"multires edges"); - - for(i=0; i<lvl->prev->totedge; ++i) { - lvl->edges[i*2].v[0]= lvl->prev->edges[i].v[0]; - lvl->edges[i*2].v[1]= lvl->prev->edges[i].mid; - lvl->edges[i*2+1].v[0]= lvl->prev->edges[i].mid; - lvl->edges[i*2+1].v[1]= lvl->prev->edges[i].v[1]; + return NULL; +} + +static void multires_load_old_edges(ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov) +{ + int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid; + vvmap[dst + mov] = emid; + + if(lvl->next->next) { + multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2); + multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2); } - /* Add edges inside of old polygons */ - curf= 0; - cure= lvl->prev->totedge*2; - for(i=0; i<lvl->prev->totface; ++i) { - for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j) { - lvl->edges[cure].v[0]= lvl->faces[curf].v[2]; - lvl->edges[cure].v[1]= lvl->faces[curf].v[3]; - ++cure; - ++curf; +} + +static void multires_load_old_faces(ListBase **fmap, ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, + int v1, int v2, int v3, int v4, int st2, int st3) +{ + int fmid; + int emid13, emid14, emid23, emid24; + + if(lvl && lvl->next) { + fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid; + vvmap[dst] = fmid; + + emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid; + emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid; + emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid; + emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid; + + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 + st3, + fmid, v2, emid23, emid24, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 + st3, + emid14, emid24, fmid, v4, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst + st2 * st3 - st3, + emid13, emid23, v3, fmid, st2, st3 / 2); + + multires_load_old_faces(fmap + 1, emap + 1, lvl->next, vvmap, dst - st2 * st3 - st3, + v1, fmid, emid13, emid14, st2, st3 / 2); + + if(lvl->next->next) { + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3); + multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3); } } +} - /* Smooth vertices - =============== */ - for(i=0; i<lvl->prev->totface; ++i) { - const MultiresFace *f= &lvl->prev->faces[i]; - data.corner1= oldverts[f->v[0]].co; - data.corner2= oldverts[f->v[1]].co; - data.corner3= oldverts[f->v[2]].co; - data.corner4= oldverts[f->v[3]].co; - data.quad= f->v[3] ? 1 : 0; - multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face); +/* Loads a multires object stored in the old Multires struct into the new format */ +void multires_load_old(DerivedMesh *dm, Multires *mr) +{ + MultiresLevel *lvl, *lvl1; + MVert *vsrc, *vdst; + int src, dst; + int totlvl = MultiresDM_get_totlvl(dm); + int st = multires_side_tot[totlvl - 2] - 1; + int extedgelen = multires_side_tot[totlvl - 1] - 2; + int *vvmap; // inorder for dst, map to src + int crossedgelen; + int i, j, s, x, totvert, tottri, totquad; + + src = 0; + dst = 0; + vsrc = mr->verts; + vdst = CDDM_get_verts(dm); + totvert = dm->getNumVerts(dm); + vvmap = MEM_callocN(sizeof(int) * totvert, "multires vvmap"); + + lvl1 = mr->levels.first; + /* Load base verts */ + for(i = 0; i < lvl1->totvert; ++i) { + vvmap[totvert - lvl1->totvert + i] = src; + ++src; } - if(subdiv_type == 0) { - for(i=0; i<lvl->prev->totedge; ++i) { - const MultiresEdge *e= &lvl->prev->edges[i]; - data.boundary= lvl->prev->edge_boundary_states[i]; - edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e); - data.endpoint1= oldverts[e->v[0]].co; - data.endpoint2= oldverts[e->v[1]].co; - multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge); - } - - for(i=0; i<lvl->prev->totvert; ++i) { - data.boundary= multires_vert_is_boundary(lvl->prev,i); - data.original= oldverts[i].co; - data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]); - if(data.boundary) - boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i); - else { - vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts, - sizeof(MVert),i); - vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts, - sizeof(MVert),i); - } - multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert); + /* Original edges */ + dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge; + for(i = 0; i < lvl1->totedge; ++i) { + int ldst = dst + extedgelen * i; + int lsrc = src; + lvl = lvl1->next; + + for(j = 2; j <= mr->level_count; ++j) { + int base = multires_side_tot[totlvl - j] - 2; + int skip = multires_side_tot[totlvl - j + 1] - 1; + int st = multires_side_tot[j - 2] - 1; + + for(x = 0; x < st; ++x) + vvmap[ldst + base + x * skip] = lsrc + st * i + x; + + lsrc += lvl->totvert - lvl->prev->totvert; + lvl = lvl->next; } } - multires_free_temp_data(lvl->prev); - MEM_freeN(oldverts); - - /* Vertex Colors - ============= */ - curf= 0; - if(me->mr->use_col) { - MultiresColFace *cf= MEM_callocN(sizeof(MultiresColFace)*lvl->totface,"Multirescolfaces"); - lvl->colfaces= cf; - for(i=0; i<lvl->prev->totface; ++i) { - const char sides= lvl->prev->faces[i].v[3]?4:3; - MultiresCol cntr; - - /* Find average color of 4 (or 3 for triangle) verts */ - multires_col_avg(&cntr,lvl->prev->colfaces[i].col,sides); - - for(j=0; j<sides; ++j) { - multires_col_avg2(&cf->col[0], - &lvl->prev->colfaces[i].col[j], - &lvl->prev->colfaces[i].col[j==0?sides-1:j-1]); - cf->col[1]= lvl->prev->colfaces[i].col[j]; - multires_col_avg2(&cf->col[2], - &lvl->prev->colfaces[i].col[j], - &lvl->prev->colfaces[i].col[j==sides-1?0:j+1]); - cf->col[3]= cntr; - - ++cf; - } - } + /* Center points */ + dst = 0; + for(i = 0; i < lvl1->totface; ++i) { + int sides = lvl1->faces[i].v[3] ? 4 : 3; + + vvmap[dst] = src + lvl1->totedge + i; + dst += 1 + sides * (st - 1) * st; } - me->mr->newlvl= me->mr->level_count; - me->mr->current= me->mr->newlvl; - /* Unless the render level has been set to something other than the - highest level (by the user), increment the render level to match - the highest available level */ - if(me->mr->renderlvl == me->mr->level_count - 1) me->mr->renderlvl= me->mr->level_count; - multires_level_to_mesh(ob, me, 0); -} + /* The rest is only for level 3 and up */ + if(lvl1->next && lvl1->next->next) { + ListBase **fmap, **emap; + IndexNode **fmem, **emem; -void multires_set_level(Object *ob, Mesh *me, const int render) -{ - if(me->pv) mesh_pmv_off(ob, me); + /* Face edge cross */ + tottri = totquad = 0; + crossedgelen = multires_side_tot[totlvl - 2] - 2; + dst = 0; + for(i = 0; i < lvl1->totface; ++i) { + int sides = lvl1->faces[i].v[3] ? 4 : 3; - check_colors(me); - multires_update_levels(me, render); + lvl = lvl1->next->next; + ++dst; - me->mr->current= me->mr->newlvl; - if(me->mr->current<1) me->mr->current= 1; - else if(me->mr->current>me->mr->level_count) me->mr->current= me->mr->level_count; + for(j = 3; j <= mr->level_count; ++j) { + int base = multires_side_tot[totlvl - j] - 2; + int skip = multires_side_tot[totlvl - j + 1] - 1; + int st = pow(2, j - 2); + int st2 = pow(2, j - 3); + int lsrc = lvl->prev->totvert; - multires_level_to_mesh(ob, me, render); -} + /* Skip exterior edge verts */ + lsrc += lvl1->totedge * st; -/* Update the edge visibility flags to only show edges on or below the edgelvl */ -void multires_edge_level_update(Object *ob, Mesh *me) -{ - if(!G.obedit) { - MultiresLevel *cr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1); - MultiresLevel *edge_lvl= BLI_findlink(&me->mr->levels,me->mr->edgelvl-1); - const int threshold= edge_lvl->totedge * pow(2, me->mr->current - me->mr->edgelvl); - unsigned i; - - for(i=0; i<cr_lvl->totedge; ++i) { - const int ndx= me->pv ? me->pv->edge_map[i] : i; - if(ndx != -1) { /* -1= hidden edge */ - if(me->mr->edgelvl >= me->mr->current || i<threshold) - me->medge[ndx].flag |= ME_EDGEDRAW | ME_EDGERENDER; - else - me->medge[ndx].flag &= ~ME_EDGEDRAW & ~ME_EDGERENDER; + /* Skip earlier face edge crosses */ + lsrc += st2 * (tottri * 3 + totquad * 4); + + for(s = 0; s < sides; ++s) { + for(x = 0; x < st2; ++x) { + vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc; + ++lsrc; + } + } + + lvl = lvl->next; } + + dst += sides * (st - 1) * st; + + if(sides == 4) ++totquad; + else ++tottri; + } - - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + /* calculate vert to edge/face maps for each level (except the last) */ + fmap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires fmap"); + emap = MEM_callocN(sizeof(ListBase*) * (mr->level_count-1), "multires emap"); + fmem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires fmem"); + emem = MEM_callocN(sizeof(IndexNode*) * (mr->level_count-1), "multires emem"); + lvl = lvl1; + for(i = 0; i < mr->level_count - 1; ++i) { + create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface); + create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge); + lvl = lvl->next; + } + + /* Interior face verts */ + lvl = lvl1->next->next; + dst = 0; + for(j = 0; j < lvl1->totface; ++j) { + int sides = lvl1->faces[j].v[3] ? 4 : 3; + int ldst = dst + 1 + sides * (st - 1); + + for(s = 0; s < sides; ++s) { + int st2 = multires_side_tot[totlvl - 2] - 2; + int st3 = multires_side_tot[totlvl - 3] - 2; + int st4 = st3 == 0 ? 1 : (st3 + 1) / 2; + int mid = ldst + st2 * st3 + st3; + int cv = lvl1->faces[j].v[s]; + int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1]; + int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1]; + + multires_load_old_faces(fmap, emap, lvl1->next, vvmap, mid, + vvmap[dst], cv, + find_old_edge(emap[0], lvl1->edges, pv, cv)->mid, + find_old_edge(emap[0], lvl1->edges, cv, nv)->mid, + st2, st4); + + ldst += (st - 1) * (st - 1); + } + + + dst = ldst; + } + + lvl = lvl->next; + + for(i = 0; i < mr->level_count - 1; ++i) { + MEM_freeN(fmap[i]); + MEM_freeN(fmem[i]); + MEM_freeN(emap[i]); + MEM_freeN(emem[i]); + } + + MEM_freeN(fmap); + MEM_freeN(emap); + MEM_freeN(fmem); + MEM_freeN(emem); } + + /* Transfer verts */ + for(i = 0; i < totvert; ++i) + VecCopyf(vdst[i].co, vsrc[vvmap[i]].co); + + MEM_freeN(vvmap); } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 245c4179bd1..dc2bf26759f 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -73,7 +73,7 @@ void copy_actionstrip (bActionStrip **dst, bActionStrip **src){ dstrip->ipo->id.us++; if (dstrip->modifiers.first) { - duplicatelist (&dstrip->modifiers, &sstrip->modifiers); + BLI_duplicatelist (&dstrip->modifiers, &sstrip->modifiers); } } @@ -84,7 +84,7 @@ void copy_nlastrips (ListBase *dst, ListBase *src) dst->first=dst->last=NULL; - duplicatelist (dst, src); + BLI_duplicatelist (dst, src); /* Update specific data */ if (!dst->first) @@ -97,7 +97,7 @@ void copy_nlastrips (ListBase *dst, ListBase *src) strip->ipo->id.us++; if (strip->modifiers.first) { ListBase listb; - duplicatelist (&listb, &strip->modifiers); + BLI_duplicatelist (&listb, &strip->modifiers); strip->modifiers= listb; } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index e4e5883b2d8..a83b8817580 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -994,7 +994,7 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) *nnode= *node; BLI_addtail(&ntree->nodes, nnode); - duplicatelist(&nnode->inputs, &node->inputs); + BLI_duplicatelist(&nnode->inputs, &node->inputs); oldsock= node->inputs.first; for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) { oldsock->new_sock= sock; @@ -1002,7 +1002,7 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) sock->own_index= 0; } - duplicatelist(&nnode->outputs, &node->outputs); + BLI_duplicatelist(&nnode->outputs, &node->outputs); oldsock= node->outputs.first; for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) { if(internal) @@ -1012,8 +1012,7 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal) oldsock->new_sock= sock; } - if(nnode->id) - nnode->id->us++; + /* don't increase node->id users, freenode doesn't decrement either */ if(node->typeinfo->copystoragefunc) node->typeinfo->copystoragefunc(node, nnode); @@ -1056,6 +1055,14 @@ bNodeTree *ntreeAddTree(int type) ntree->type= type; ntree->alltypes.first = NULL; ntree->alltypes.last = NULL; + + /* this helps RNA identify ID pointers as nodetree */ + if(ntree->type==NTREE_SHADER) + BLI_strncpy(ntree->id.name, "NTShader Nodetree", sizeof(ntree->id.name)); + else if(ntree->type==NTREE_COMPOSIT) + BLI_strncpy(ntree->id.name, "NTComposit Nodetree", sizeof(ntree->id.name)); + else if(ntree->type==NTREE_TEXTURE) + BLI_strncpy(ntree->id.name, "NTTexture Nodetree", sizeof(ntree->id.name)); ntreeInitTypes(ntree); return ntree; @@ -1124,7 +1131,8 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select) /* check for copying links */ for(link= ntree->links.first; link; link= link->next) { - if(link->fromnode->new_node && link->tonode->new_node) { + if(link->fromnode==NULL || link->tonode==NULL); + else if(link->fromnode->new_node && link->tonode->new_node) { nlink= nodeAddLink(newtree, link->fromnode->new_node, NULL, link->tonode->new_node, NULL); /* sockets were copied in order */ for(a=0, sock= link->fromnode->outputs.first; sock; sock= sock->next, a++) { @@ -1158,6 +1166,104 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select) return newtree; } +/* *************** preview *********** */ +/* if node->preview, then we assume the rect to exist */ + +static void node_free_preview(bNode *node) +{ + if(node->preview) { + if(node->preview->rect) + MEM_freeN(node->preview->rect); + MEM_freeN(node->preview); + node->preview= NULL; + } +} + +static void node_init_preview(bNode *node, int xsize, int ysize) +{ + + if(node->preview==NULL) { + node->preview= MEM_callocN(sizeof(bNodePreview), "node preview"); + // printf("added preview %s\n", node->name); + } + + /* node previews can get added with variable size this way */ + if(xsize==0 || ysize==0) + return; + + /* sanity checks & initialize */ + if(node->preview->rect) { + if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) { + MEM_freeN(node->preview->rect); + node->preview->rect= NULL; + } + } + + if(node->preview->rect==NULL) { + node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect"); + node->preview->xsize= xsize; + node->preview->ysize= ysize; + } +} + +void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) +{ + bNode *node; + + if(ntree==NULL) + return; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */ + node_init_preview(node, xsize, ysize); + if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) + ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); + } +} + +static void nodeClearPreview(bNode *node) +{ + if(node->preview && node->preview->rect) + memset(node->preview->rect, 0, MEM_allocN_len(node->preview->rect)); +} + +/* use it to enforce clear */ +void ntreeClearPreview(bNodeTree *ntree) +{ + bNode *node; + + if(ntree==NULL) + return; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->flag & NODE_PREVIEW) + nodeClearPreview(node); + if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) + ntreeClearPreview((bNodeTree *)node->id); + } +} + +/* hack warning! this function is only used for shader previews, and +since it gets called multiple times per pixel for Ztransp we only +add the color once. Preview gets cleared before it starts render though */ +void nodeAddToPreview(bNode *node, float *col, int x, int y) +{ + bNodePreview *preview= node->preview; + if(preview) { + if(x>=0 && y>=0) { + if(x<preview->xsize && y<preview->ysize) { + float *tar= preview->rect+ 4*((preview->xsize*y) + x); + //if(tar[0]==0.0f) { + QUATCOPY(tar, col); + //} + } + //else printf("prv out bound x y %d %d\n", x, y); + } + //else printf("prv out bound x y %d %d\n", x, y); + } +} + + /* ************** Free stuff ********** */ /* goes over entire tree */ @@ -1215,11 +1321,8 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) BLI_freelistN(&node->inputs); BLI_freelistN(&node->outputs); - if(node->preview) { - if(node->preview->rect) - MEM_freeN(node->preview->rect); - MEM_freeN(node->preview); - } + node_free_preview(node); + if(node->typeinfo && node->typeinfo->freestoragefunc) { node->typeinfo->freestoragefunc(node); } @@ -1653,14 +1756,8 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node) for(sock= node->outputs.first; sock; sock= sock->next) { if(sock->ns.data) { - free_compbuf(sock->ns.data); - sock->ns.data= NULL; - - //if(node->preview && node->preview->rect) { - // MEM_freeN(node->preview->rect); - // node->preview->rect= NULL; - //} - + //free_compbuf(sock->ns.data); + //sock->ns.data= NULL; } } node->need_exec= 1; @@ -1682,95 +1779,6 @@ void NodeTagIDChanged(bNodeTree *ntree, ID *id) } -/* *************** preview *********** */ - -/* if node->preview, then we assume the rect to exist */ - -static void nodeInitPreview(bNode *node, int xsize, int ysize) -{ - - if(node->preview==NULL) { - node->preview= MEM_callocN(sizeof(bNodePreview), "node preview"); -// printf("added preview %s\n", node->name); - } - - /* node previews can get added with variable size this way */ - if(xsize==0 || ysize==0) - return; - - /* sanity checks & initialize */ - if(node->preview->rect) { - if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) { - MEM_freeN(node->preview->rect); - node->preview->rect= NULL; - } - } - - if(node->preview->rect==NULL) { - node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect"); - node->preview->xsize= xsize; - node->preview->ysize= ysize; - } -} - -void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) -{ - bNode *node; - - if(ntree==NULL) - return; - - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */ - nodeInitPreview(node, xsize, ysize); - if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) - ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); - } -} - -static void nodeClearPreview(bNode *node) -{ - if(node->preview && node->preview->rect) - memset(node->preview->rect, 0, MEM_allocN_len(node->preview->rect)); -} - -/* use it to enforce clear */ -void ntreeClearPreview(bNodeTree *ntree) -{ - bNode *node; - - if(ntree==NULL) - return; - - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->flag & NODE_PREVIEW) - nodeClearPreview(node); - if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) - ntreeClearPreview((bNodeTree *)node->id); - } -} - -/* hack warning! this function is only used for shader previews, and - since it gets called multiple times per pixel for Ztransp we only - add the color once. Preview gets cleared before it starts render though */ -void nodeAddToPreview(bNode *node, float *col, int x, int y) -{ - bNodePreview *preview= node->preview; - if(preview) { - if(x>=0 && y>=0) { - if(x<preview->xsize && y<preview->ysize) { - float *tar= preview->rect+ 4*((preview->xsize*y) + x); - if(tar[0]==0.0f) { - QUATCOPY(tar, col); - } - } - //else printf("prv out bound x y %d %d\n", x, y); - } - //else printf("prv out bound x y %d %d\n", x, y); - } -} - - /* ******************* executing ************* */ @@ -1982,9 +1990,9 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack) } } +/* notes below are ancient! (ton) */ /* stack indices make sure all nodes only write in allocated data, for making it thread safe */ /* only root tree gets the stack, to enable instances to have own stack entries */ -/* only two threads now! */ /* per tree (and per group) unique indices are created */ /* the index_ext we need to be able to map from groups to the group-node own stack */ @@ -1999,14 +2007,9 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) ListBase *lb= &ntree->threadstack[thread]; bNodeThreadStack *nts; - /* for material shading this is called quite a lot (perhaps too much locking unlocking) - * however without locking we get bug #18058 - Campbell */ - BLI_lock_thread(LOCK_CUSTOM1); - for(nts=lb->first; nts; nts=nts->next) { if(!nts->used) { nts->used= 1; - BLI_unlock_thread(LOCK_CUSTOM1); return nts; } } @@ -2014,7 +2017,7 @@ static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) nts->stack= MEM_dupallocN(ntree->stack); nts->used= 1; BLI_addtail(lb, nts); - BLI_unlock_thread(LOCK_CUSTOM1); + return nts; } @@ -2228,7 +2231,7 @@ static void *exec_composite_node(void *node_v) bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ bNode *node= node_v; - ThreadData *thd= (ThreadData *)node->new_node; /* abuse */ + ThreadData *thd= (ThreadData *)node->threaddata; node_get_stack(node, thd->stack, nsin, nsout); @@ -2292,8 +2295,10 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) /* is sock in use? */ else if(sock->link) { bNodeLink *link= sock->link; + /* this is the test for a cyclic case */ - if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { + if(link->fromnode==NULL || link->tonode==NULL); + else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { if(link->fromnode->need_exec) { node->need_exec= 1; break; @@ -2323,7 +2328,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) } else { /* tag for getExecutableNode() */ - node->exec= NODE_READY|NODE_FINISHED; + node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED; } } @@ -2433,7 +2438,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) /* sets need_exec tags in nodes */ totnode= setExecutableNodes(ntree, &thdata); - + BLI_init_threads(&threads, exec_composite_node, rd->threads); while(rendering) { @@ -2441,17 +2446,17 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) if(BLI_available_threads(&threads)) { node= getExecutableNode(ntree); if(node) { - + if(ntree->timecursor) - ntree->timecursor(totnode); + ntree->timecursor(ntree->tch, totnode); if(ntree->stats_draw) { char str[64]; sprintf(str, "Compositing %d %s", totnode, node->name); - ntree->stats_draw(str); + ntree->stats_draw(ntree->sdh, str); } totnode--; - node->new_node = (bNode *)&thdata; + node->threaddata = &thdata; node->exec= NODE_PROCESSING; BLI_insert_thread(&threads, node); } @@ -2463,7 +2468,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) rendering= 0; /* test for ESC */ - if(ntree->test_break && ntree->test_break()) { + if(ntree->test_break && ntree->test_break(ntree->tbh)) { for(node= ntree->nodes.first; node; node= node->next) node->exec |= NODE_READY; } @@ -2484,12 +2489,131 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) } } - BLI_end_threads(&threads); ntreeEndExecTree(ntree); } + +/* ********** copy composite tree entirely, to allow threaded exec ******************* */ +/* ***************** do NOT execute this in a thread! ****************** */ + +/* returns localized composite tree for execution in threads */ +/* local tree then owns all compbufs */ +bNodeTree *ntreeLocalize(bNodeTree *ntree) +{ + bNodeTree *ltree= ntreeCopyTree(ntree, 0); + bNode *node; + bNodeSocket *sock; + + /* move over the compbufs */ + /* right after ntreeCopyTree() oldsock pointers are valid */ + for(node= ntree->nodes.first; node; node= node->next) { + + /* store new_node pointer to original */ + node->new_node->new_node= node; + /* ensure new user input gets handled ok */ + node->need_exec= 0; + + if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if(node->id) { + if(node->flag & NODE_DO_OUTPUT) + node->new_node->id= (ID *)BKE_image_copy((Image *)node->id); + else + node->new_node->id= NULL; + } + } + + for(sock= node->outputs.first; sock; sock= sock->next) { + + sock->new_sock->ns.data= sock->ns.data; + sock->ns.data= NULL; + sock->new_sock->new_sock= sock; + } + } + + return ltree; +} + +static int node_exists(bNodeTree *ntree, bNode *testnode) +{ + bNode *node= ntree->nodes.first; + for(; node; node= node->next) + if(node==testnode) + return 1; + return 0; +} + +static int outsocket_exists(bNode *node, bNodeSocket *testsock) +{ + bNodeSocket *sock= node->outputs.first; + for(; sock; sock= sock->next) + if(sock==testsock) + return 1; + return 0; +} + + +/* sync local composite with real tree */ +/* local composite is supposed to be running, be careful moving previews! */ +void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) +{ + bNode *lnode; + + /* move over the compbufs and previews */ + for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) { + if(node_exists(ntree, lnode->new_node)) { + + if(lnode->preview && lnode->preview->rect) { + node_free_preview(lnode->new_node); + lnode->new_node->preview= lnode->preview; + lnode->preview= NULL; + } + } + } + } +} + +/* merge local tree results back, and free local tree */ +/* we have to assume the editor already changed completely */ +void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) +{ + bNode *lnode; + bNodeSocket *lsock; + + /* move over the compbufs and previews */ + for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { + if(node_exists(ntree, lnode->new_node)) { + + if(lnode->preview && lnode->preview->rect) { + node_free_preview(lnode->new_node); + lnode->new_node->preview= lnode->preview; + lnode->preview= NULL; + } + + if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) { + /* image_merge does sanity check for pointers */ + BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id); + } + } + + for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) { + if(outsocket_exists(lnode->new_node, lsock->new_sock)) { + lsock->new_sock->ns.data= lsock->ns.data; + lsock->ns.data= NULL; + lsock->new_sock= NULL; + } + } + } + } + ntreeFreeTree(localtree); + MEM_freeN(localtree); +} + +/* *********************************************** */ + /* GPU material from shader nodes */ static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) @@ -2651,7 +2775,7 @@ static void force_hidden_passes(bNode *node, int passflag) } /* based on rules, force sockets hidden always */ -void ntreeCompositForceHidden(bNodeTree *ntree) +void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene) { bNode *node; @@ -2659,7 +2783,7 @@ void ntreeCompositForceHidden(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if( node->type==CMP_NODE_R_LAYERS) { - Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */ + Scene *sce= node->id?(Scene *)node->id:curscene; SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); if(srl) force_hidden_passes(node, srl->passflag); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0b153c3c065..81bd78f1851 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -39,13 +39,13 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_group_types.h" -#include "DNA_ipo_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_material_types.h" @@ -58,7 +58,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_object_fluidsim.h" -#include "DNA_oops_types.h" +#include "DNA_outliner_types.h" #include "DNA_particle_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -68,24 +68,23 @@ #include "DNA_view3d_types.h" #include "DNA_world_types.h" -#include "BKE_armature.h" -#include "BKE_action.h" -#include "BKE_bullet.h" -#include "BKE_colortools.h" -#include "BKE_deform.h" -#include "BKE_DerivedMesh.h" -#include "BKE_nla.h" - #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_editVert.h" #include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h" #include "BKE_main.h" #include "BKE_global.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_bullet.h" +#include "BKE_colortools.h" +#include "BKE_deform.h" +#include "BKE_DerivedMesh.h" +#include "BKE_nla.h" +#include "BKE_animsys.h" #include "BKE_anim.h" #include "BKE_blender.h" #include "BKE_constraint.h" @@ -93,7 +92,6 @@ #include "BKE_displist.h" #include "BKE_group.h" #include "BKE_icons.h" -#include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -117,25 +115,22 @@ #include "GPU_material.h" -#include "blendef.h" - /* Local function protos */ -static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul); +static void solve_parenting (Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul); float originmat[3][3]; /* after where_is_object(), can be used in other functions (bad!) */ -Object workob; -void clear_workob(void) +void clear_workob(Object *workob) { - memset(&workob, 0, sizeof(Object)); + memset(workob, 0, sizeof(Object)); - workob.size[0]= workob.size[1]= workob.size[2]= 1.0; + workob->size[0]= workob->size[1]= workob->size[2]= 1.0; } -void copy_baseflags() +void copy_baseflags(struct Scene *scene) { - Base *base= G.scene->base.first; + Base *base= scene->base.first; while(base) { base->object->flag= base->flag; @@ -143,9 +138,9 @@ void copy_baseflags() } } -void copy_objectflags() +void copy_objectflags(struct Scene *scene) { - Base *base= G.scene->base.first; + Base *base= scene->base.first; while(base) { base->flag= base->object->flag; @@ -153,9 +148,9 @@ void copy_objectflags() } } -void update_base_layer(Object *ob) +void update_base_layer(struct Scene *scene, Object *ob) { - Base *base= G.scene->base.first; + Base *base= scene->base.first; while (base) { if (base->object == ob) base->lay= ob->lay; @@ -253,8 +248,7 @@ void free_object(Object *ob) ob->bb= 0; if(ob->path) free_path(ob->path); ob->path= 0; - if(ob->ipo) ob->ipo->id.us--; - if(ob->action) ob->action->id.us--; + if(ob->adt) BKE_free_animdata((ID *)ob); if(ob->poselib) ob->poselib->id.us--; if(ob->dup_group) ob->dup_group->id.us--; if(ob->defbase.first) @@ -269,8 +263,6 @@ void free_object(Object *ob) free_actuators(&ob->actuators); free_constraints(&ob->constraints); - free_constraint_channels(&ob->constraintChannels); - free_nlastrips(&ob->nlastrips); #ifndef DISABLE_PYTHON BPY_free_scriptlink(&ob->scriptlink); @@ -295,7 +287,7 @@ static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Objec ob->recalc |= OB_RECALC; } } -void unlink_object(Object *ob) +void unlink_object(Scene *scene, Object *ob) { Object *obt; Material *mat; @@ -304,11 +296,10 @@ void unlink_object(Object *ob) Scene *sce; Curve *cu; Tex *tex; - Ipo *ipo; Group *group; Camera *camera; bConstraint *con; - bActionStrip *strip; + //bActionStrip *strip; // XXX animsys ModifierData *md; int a; @@ -418,6 +409,7 @@ void unlink_object(Object *ob) } /* strips */ +#if 0 // XXX old animation system for(strip= obt->nlastrips.first; strip; strip= strip->next) { if(strip->object==ob) strip->object= NULL; @@ -429,6 +421,7 @@ void unlink_object(Object *ob) amod->ob= NULL; } } +#endif // XXX old animation system /* particle systems */ if(obt->particlesystem.first) { @@ -497,9 +490,9 @@ void unlink_object(Object *ob) tex= tex->id.next; } - /* mballs */ - if(ob->type==OB_MBALL) { - obt= find_basis_mball(ob); + /* mballs (scene==NULL when called from library.c) */ + if(scene && ob->type==OB_MBALL) { + obt= find_basis_mball(scene, ob); if(obt) freedisplist(&obt->disp); } @@ -525,6 +518,8 @@ void unlink_object(Object *ob) } sce= sce->id.next; } + +#if 0 // XXX old animation system /* ipos */ ipo= G.main->ipo.first; while(ipo) { @@ -537,6 +532,7 @@ void unlink_object(Object *ob) } ipo= ipo->id.next; } +#endif // XXX old animation system /* screens */ sc= G.main->screen.first; @@ -551,26 +547,16 @@ void unlink_object(Object *ob) if(v3d->camera==ob) { v3d->camera= NULL; - if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP; + // XXX if(v3d->persp==V3D_CAMOB) v3d->persp= V3D_PERSP; } if(v3d->localvd && v3d->localvd->camera==ob ) { v3d->localvd->camera= NULL; - if(v3d->localvd->persp==V3D_CAMOB) v3d->localvd->persp= V3D_PERSP; + // XXX if(v3d->localvd->persp==V3D_CAMOB) v3d->localvd->persp= V3D_PERSP; } } - else if(sl->spacetype==SPACE_IPO) { - SpaceIpo *sipo= (SpaceIpo *)sl; - if(sipo->from == (ID *)ob) sipo->from= NULL; - } - else if(sl->spacetype==SPACE_OOPS) { + else if(sl->spacetype==SPACE_OUTLINER) { SpaceOops *so= (SpaceOops *)sl; - Oops *oops; - oops= so->oops.first; - while(oops) { - if(oops->id==(ID *)ob) oops->id= NULL; - oops= oops->next; - } if(so->treestore) { TreeStoreElem *tselem= so->treestore->data; int a; @@ -578,7 +564,6 @@ void unlink_object(Object *ob) if(tselem->id==(ID *)ob) tselem->id= NULL; } } - so->lockpoin= NULL; } } @@ -641,7 +626,8 @@ Camera *copy_camera(Camera *cam) Camera *camn; camn= copy_libblock(cam); - id_us_plus((ID *)camn->ipo); + camn->adt= BKE_copy_animdata(cam->adt); + #ifndef DISABLE_PYTHON BPY_copy_scriptlink(&camn->scriptlink); #endif @@ -707,7 +693,7 @@ float dof_camera(Object *ob) { Camera *cam = (Camera *)ob->data; if (ob->type != OB_CAMERA) - return 0.0; + return 0.0f; if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */ @@ -717,7 +703,7 @@ float dof_camera(Object *ob) Mat4Ortho(obmat); Mat4Invert(ob->imat, obmat); Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat); - return fabs(mat[3][2]); + return (float)fabs(mat[3][2]); } return cam->YF_dofdist; } @@ -728,26 +714,26 @@ void *add_lamp(char *name) la= alloc_libblock(&G.main->lamp, ID_LA, name); - la->r= la->g= la->b= la->k= 1.0; - la->haint= la->energy= 1.0; - la->dist= 20.0; - la->spotsize= 45.0; - la->spotblend= 0.15; - la->att2= 1.0; + la->r= la->g= la->b= la->k= 1.0f; + la->haint= la->energy= 1.0f; + la->dist= 20.0f; + la->spotsize= 45.0f; + la->spotblend= 0.15f; + la->att2= 1.0f; la->mode= LA_SHAD_BUF; la->bufsize= 512; - la->clipsta= 0.5; - la->clipend= 40.0; - la->shadspotsize= 45.0; + la->clipsta= 0.5f; + la->clipend= 40.0f; + la->shadspotsize= 45.0f; la->samp= 3; - la->bias= 1.0; - la->soft= 3.0; + la->bias= 1.0f; + la->soft= 3.0f; la->ray_samp= la->ray_sampy= la->ray_sampz= 1; - la->area_size=la->area_sizey=la->area_sizez= 1.0; + la->area_size=la->area_sizey=la->area_sizez= 1.0f; la->buffers= 1; la->buftype= LA_SHADBUF_HALFWAY; la->ray_samp_method = LA_SAMP_HALTON; - la->adapt_thresh = 0.001; + la->adapt_thresh = 0.001f; la->preview=NULL; la->falloff_type = LA_FALLOFF_INVLINEAR; la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f); @@ -756,12 +742,12 @@ void *add_lamp(char *name) la->spread = 1.0; la->sun_brightness = 1.0; la->sun_size = 1.0; - la->backscattered_light = 1.0; - la->atm_turbidity = 2.0; - la->atm_inscattering_factor = 1.0; - la->atm_extinction_factor = 1.0; - la->atm_distance_factor = 1.0; - la->sun_intensity = 1.0; + la->backscattered_light = 1.0f; + la->atm_turbidity = 2.0f; + la->atm_inscattering_factor = 1.0f; + la->atm_extinction_factor = 1.0f; + la->atm_distance_factor = 1.0f; + la->sun_intensity = 1.0f; la->skyblendtype= MA_RAMP_ADD; la->skyblendfac= 1.0f; la->sky_colorspace= BLI_CS_CIE; @@ -788,7 +774,9 @@ Lamp *copy_lamp(Lamp *la) lan->curfalloff = curvemapping_copy(la->curfalloff); +#if 0 // XXX old animation system id_us_plus((ID *)lan->ipo); +#endif // XXX old animation system if (la->preview) lan->preview = BKE_previewimg_copy(la->preview); #ifndef DISABLE_PYTHON @@ -854,6 +842,7 @@ void free_camera(Camera *ca) #ifndef DISABLE_PYTHON BPY_free_scriptlink(&ca->scriptlink); #endif + BKE_free_animdata((ID *)ca); } void free_lamp(Lamp *la) @@ -871,7 +860,8 @@ void free_lamp(Lamp *la) if(mtex && mtex->tex) mtex->tex->id.us--; if(mtex) MEM_freeN(mtex); } - la->ipo= 0; + + BKE_free_animdata((ID *)la); curvemapping_free(la->curfalloff); @@ -891,13 +881,13 @@ void *add_wave() static void *add_obdata_from_type(int type) { switch (type) { - case OB_MESH: G.totmesh++; return add_mesh("Mesh"); - case OB_CURVE: G.totcurve++; return add_curve("Curve", OB_CURVE); - case OB_SURF: G.totcurve++; return add_curve("Surf", OB_SURF); + case OB_MESH: return add_mesh("Mesh"); + case OB_CURVE: return add_curve("Curve", OB_CURVE); + case OB_SURF: return add_curve("Surf", OB_SURF); case OB_FONT: return add_curve("Text", OB_FONT); case OB_MBALL: return add_mball("Meta"); case OB_CAMERA: return add_camera("Camera"); - case OB_LAMP: G.totlamp++; return add_lamp("Lamp"); + case OB_LAMP: return add_lamp("Lamp"); case OB_LATTICE: return add_lattice("Lattice"); case OB_WAVE: return add_wave(); case OB_ARMATURE: return add_armature("Armature"); @@ -934,7 +924,6 @@ Object *add_only_object(int type, char *name) Object *ob; ob= alloc_libblock(&G.main->object, ID_OB, name); - G.totobj++; /* default object vars */ ob->type= type; @@ -968,8 +957,12 @@ Object *add_only_object(int type, char *name) ob->trackflag= OB_POSY; ob->upflag= OB_POSZ; } + +#if 0 // XXX old animation system ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT; ob->ipowin= ID_OB; /* the ipowin shown */ +#endif // XXX old animation system + ob->dupon= 1; ob->dupoff= 0; ob->dupsta= 1; ob->dupend= 100; ob->dupfacesca = 1.0; @@ -984,6 +977,8 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[2] = 1.0f; ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; + /* ob->pad3 == Contact Processing Threshold */ + ob->m_contactProcessingThreshold = 1.; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; @@ -992,9 +987,9 @@ Object *add_only_object(int type, char *name) return ob; } -/* general add: to G.scene, with layer from area and default name */ +/* general add: to scene, with layer from area and default name */ /* creates minimum required data, but without vertices etc. */ -Object *add_object(int type) +Object *add_object(struct Scene *scene, int type) { Object *ob; Base *base; @@ -1005,47 +1000,15 @@ Object *add_object(int type) ob->data= add_obdata_from_type(type); - ob->lay= G.scene->lay; + ob->lay= scene->lay; - base= scene_add_base(G.scene, ob); - scene_select_base(G.scene, base); + base= scene_add_base(scene, ob); + scene_select_base(scene, base); ob->recalc |= OB_RECALC; return ob; } -void base_init_from_view3d(Base *base, View3D *v3d) -{ - Object *ob= base->object; - - if (!v3d) { - /* no 3d view, this wont happen often */ - base->lay = 1; - VECCOPY(ob->loc, G.scene->cursor); - - /* return now because v3d->viewquat isnt available */ - return; - } else if (v3d->localview) { - base->lay= ob->lay= v3d->layact + v3d->lay; - VECCOPY(ob->loc, v3d->cursor); - } else { - base->lay= ob->lay= v3d->layact; - VECCOPY(ob->loc, G.scene->cursor); - } - - if (U.flag & USER_ADD_VIEWALIGNED) { - v3d->viewquat[0]= -v3d->viewquat[0]; - - /* Quats arnt used yet */ - /*if (ob->transflag & OB_QUAT) { - QUATCOPY(ob->quat, v3d->viewquat); - } else {*/ - QuatToEul(v3d->viewquat, ob->rot); - /*}*/ - v3d->viewquat[0]= -v3d->viewquat[0]; - } -} - SoftBody *copy_softbody(SoftBody *sb) { SoftBody *sbn; @@ -1164,16 +1127,21 @@ static void copy_object_pose(Object *obn, Object *ob) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; +#if 0 // XXX old animation system /* note that we can't change lib linked ipo blocks. for making * proxies this still works correct however because the object * is changed to object->proxy_from when evaluating the driver. */ if(con->ipo && !con->ipo->id.lib) { IpoCurve *icu; + + con->ipo= copy_ipo(con->ipo); + for(icu= con->ipo->curve.first; icu; icu= icu->next) { if(icu->driver && icu->driver->ob==ob) icu->driver->ob= obn; } } +#endif // XXX old animation system if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); @@ -1230,15 +1198,17 @@ Object *copy_object(Object *ob) armature_rebuild_pose(obn, obn->data); } copy_defgroups(&obn->defbase, &ob->defbase); +#if 0 // XXX old animation system copy_nlastrips(&obn->nlastrips, &ob->nlastrips); - copy_constraints (&obn->constraints, &ob->constraints); - - clone_constraint_channels (&obn->constraintChannels, &ob->constraintChannels); +#endif // XXX old animation system + copy_constraints(&obn->constraints, &ob->constraints); /* increase user numbers */ id_us_plus((ID *)obn->data); +#if 0 // XXX old animation system id_us_plus((ID *)obn->ipo); id_us_plus((ID *)obn->action); +#endif // XXX old animation system id_us_plus((ID *)obn->dup_group); for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); @@ -1258,10 +1228,6 @@ Object *copy_object(Object *ob) obn->derivedDeform = NULL; obn->derivedFinal = NULL; -#ifdef WITH_VERSE - obn->vnode = NULL; -#endif - obn->gpulamp.first = obn->gpulamp.last = NULL; return obn; @@ -1269,21 +1235,25 @@ Object *copy_object(Object *ob) void expand_local_object(Object *ob) { - bActionStrip *strip; + //bActionStrip *strip; ParticleSystem *psys; int a; - + +#if 0 // XXX old animation system id_lib_extern((ID *)ob->action); id_lib_extern((ID *)ob->ipo); +#endif // XXX old animation system id_lib_extern((ID *)ob->data); id_lib_extern((ID *)ob->dup_group); for(a=0; a<ob->totcol; a++) { id_lib_extern((ID *)ob->mat[a]); } +#if 0 // XXX old animation system for (strip=ob->nlastrips.first; strip; strip=strip->next) { id_lib_extern((ID *)strip->act); } +#endif // XXX old animation system for(psys=ob->particlesystem.first; psys; psys=psys->next) id_lib_extern((ID *)psys->part); } @@ -1355,6 +1325,18 @@ void make_local_object(Object *ob) expand_local_object(ob); } +/* returns true if the Object data is a from an external blend file (libdata) */ +int object_data_is_libdata(Object *ob) +{ + if(!ob) return 0; + if(ob->proxy) return 0; + if(ob->id.lib) return 1; + if(!ob->data) return 0; + if(((ID *)ob->data)->lib) return 1; + + return 0; +} + /* *************** PROXY **************** */ /* when you make proxy, ensure the exposed layers are extern */ @@ -1405,7 +1387,9 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) ob->parent= target->parent; /* libdata */ Mat4CpyMat4(ob->parentinv, target->parentinv); +#if 0 // XXX old animation system ob->ipo= target->ipo; /* libdata */ +#endif // XXX old animation system /* skip constraints, constraintchannels, nla? */ @@ -1418,7 +1402,7 @@ void object_make_proxy(Object *ob, Object *target, Object *gob) ob->actcol= ob->totcol= 0; if(ob->mat) MEM_freeN(ob->mat); ob->mat = NULL; - if ((target->totcol) && (target->mat) && OB_SUPPORT_MATERIAL(ob)) { + if ((target->totcol) && (target->mat) && ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { //XXX OB_SUPPORT_MATERIAL int i; ob->colbits = target->colbits; @@ -1466,8 +1450,9 @@ void disable_speed_curve(int val) no_speed_curve= val; } +// XXX THIS CRUFT NEEDS SERIOUS RECODING ASAP! /* ob can be NULL */ -float bsystem_time(Object *ob, float cfra, float ofs) +float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs) { /* returns float ( see frame_to_float in ipo.c) */ @@ -1475,8 +1460,9 @@ float bsystem_time(Object *ob, float cfra, float ofs) cfra+= bluroffs+fieldoffs; /* global time */ - cfra*= G.scene->r.framelen; + cfra*= scene->r.framelen; +#if 0 // XXX old animation system if (ob) { if (no_speed_curve==0 && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra); @@ -1485,6 +1471,7 @@ float bsystem_time(Object *ob, float cfra, float ofs) if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) cfra-= give_timeoffset(ob); } +#endif // XXX old animation system cfra-= ofs; @@ -1563,7 +1550,7 @@ void object_to_mat4(Object *ob, float mat[][4]) int enable_cu_speed= 1; -static void ob_parcurve(Object *ob, Object *par, float mat[][4]) +static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[][4]) { Curve *cu; float q[4], vec[4], dir[3], quat[4], x1, ctime; @@ -1573,7 +1560,7 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) cu= par->data; if(cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */ - makeDispListCurveTypes(par, 0); + makeDispListCurveTypes(scene, par, 0); if(cu->path==NULL) return; /* exception, timeoffset is regarded as distance offset */ @@ -1588,15 +1575,17 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) } /* catch exceptions: curve paths used as a duplicator */ else if(enable_cu_speed) { - ctime= bsystem_time(ob, (float)G.scene->r.cfra, 0.0); + ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0); +#if 0 // XXX old animation system if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { ctime /= cu->pathlen; CLAMP(ctime, 0.0, 1.0); } +#endif // XXX old animation system } else { - ctime= G.scene->r.cfra - give_timeoffset(ob); + ctime= scene->r.cfra - give_timeoffset(ob); ctime /= cu->pathlen; CLAMP(ctime, 0.0, 1.0); @@ -1637,11 +1626,9 @@ static void ob_parcurve(Object *ob, Object *par, float mat[][4]) static void ob_parbone(Object *ob, Object *par, float mat[][4]) { bPoseChannel *pchan; - bArmature *arm; float vec[3]; - arm=get_armature(par); - if (!arm) { + if (par->type!=OB_ARMATURE) { Mat4One(mat); return; } @@ -1665,13 +1652,16 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) static void give_parvert(Object *par, int nr, float *vec) { + EditMesh *em; int a, count; vec[0]=vec[1]=vec[2]= 0.0f; if(par->type==OB_MESH) { - if(G.obedit && (par->data==G.obedit->data)) { - EditMesh *em = G.editMesh; + Mesh *me= par->data; + em = BKE_mesh_get_editmesh(me); + + if(em) { EditVert *eve; for(eve= em->verts.first; eve; eve= eve->next) { @@ -1680,6 +1670,7 @@ static void give_parvert(Object *par, int nr, float *vec) break; } } + BKE_mesh_end_editmesh(me, em); } else { DerivedMesh *dm = par->derivedFinal; @@ -1709,7 +1700,7 @@ static void give_parvert(Object *par, int nr, float *vec) } } } - else if ELEM(par->type, OB_CURVE, OB_SURF) { + else if (ELEM(par->type, OB_CURVE, OB_SURF)) { Nurb *nu; Curve *cu; BPoint *bp; @@ -1717,8 +1708,10 @@ static void give_parvert(Object *par, int nr, float *vec) int found= 0; cu= par->data; - nu= cu->nurb.first; - if(par==G.obedit) nu= editNurb.first; + if(cu->editnurb) + nu= cu->editnurb->first; + else + nu= cu->nurb.first; count= 0; while(nu && !found) { @@ -1758,7 +1751,7 @@ static void give_parvert(Object *par, int nr, float *vec) DispList *dl = find_displist(&par->disp, DL_VERTS); float *co = dl?dl->verts:NULL; - if(par==G.obedit) latt= editLatt; + if(latt->editlatt) latt= latt->editlatt; a= latt->pntsu*latt->pntsv*latt->pntsw; count= 0; @@ -1785,7 +1778,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4]) /* in local ob space */ Mat4One(mat); - if ELEM4(par->type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE) { + if (ELEM4(par->type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE)) { give_parvert(par, ob->par1, v1); give_parvert(par, ob->par2, v2); @@ -1806,6 +1799,7 @@ static void ob_parvert3(Object *ob, Object *par, float mat[][4]) } } +// XXX what the hell is this? static int no_parent_ipo=0; void set_no_parent_ipo(int val) { @@ -1832,10 +1826,10 @@ int during_scriptlink(void) { return during_scriptlink_flag; } -void where_is_object_time(Object *ob, float ctime) +void where_is_object_time(Scene *scene, Object *ob, float ctime) { float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY; - float stime, fac1, fac2, vec[3]; + float stime=ctime, fac1, fac2, vec[3]; int a; int pop; @@ -1845,8 +1839,9 @@ void where_is_object_time(Object *ob, float ctime) if(ob==NULL) return; +#if 0 // XXX old animation system /* this is needed to be able to grab objects with ipos, otherwise it always freezes them */ - stime= bsystem_time(ob, ctime, 0.0); + stime= bsystem_time(scene, ob, ctime, 0.0); if(stime != ob->ctime) { ob->ctime= stime; @@ -1856,7 +1851,7 @@ void where_is_object_time(Object *ob, float ctime) execute_ipo((ID *)ob, ob->ipo); } else - do_all_object_actions(ob); + do_all_object_actions(scene, ob); /* do constraint ipos ..., note it needs stime (0 = all ipos) */ do_constraint_channels(&ob->constraints, &ob->constraintChannels, stime, 0); @@ -1867,36 +1862,39 @@ void where_is_object_time(Object *ob, float ctime) /* do constraint ipos ..., note it needs stime (1 = only drivers ipos) */ do_constraint_channels(&ob->constraints, &ob->constraintChannels, stime, 1); } +#endif // XXX old animation system + + /* execute drivers only, as animation has already been done */ + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_DRIVERS); if(ob->parent) { Object *par= ob->parent; + // XXX depreceated - animsys if(ob->ipoflag & OB_OFFS_PARENT) ctime-= give_timeoffset(ob); /* hurms, code below conflicts with depgraph... (ton) */ /* and even worse, it gives bad effects for NLA stride too (try ctime != par->ctime, with MBlur) */ pop= 0; if(no_parent_ipo==0 && stime != par->ctime) { - // only for ipo systems? pushdata(par, sizeof(Object)); pop= 1; if(par->proxy_from); // was a copied matrix, no where_is! bad... - else where_is_object_time(par, ctime); + else where_is_object_time(scene, par, ctime); } - solve_parenting(ob, par, ob->obmat, slowmat, 0); - + solve_parenting(scene, ob, par, ob->obmat, slowmat, 0); + if(pop) { poplast(par); } if(ob->partype & PARSLOW) { // include framerate - - fac1= (1.0f/(1.0f+ fabs(give_timeoffset(ob)))); - if(fac1>=1.0) return; + fac1= ( 1.0f / (1.0f + (float)fabs(give_timeoffset(ob))) ); + if(fac1 >= 1.0f) return; fac2= 1.0f-fac1; fp1= ob->obmat[0]; @@ -1905,7 +1903,6 @@ void where_is_object_time(Object *ob, float ctime) fp1[0]= fac1*fp1[0] + fac2*fp2[0]; } } - } else { object_to_mat4(ob, ob->obmat); @@ -1913,16 +1910,15 @@ void where_is_object_time(Object *ob, float ctime) /* Handle tracking */ if(ob->track) { - if( ctime != ob->track->ctime) where_is_object_time(ob->track, ctime); + if( ctime != ob->track->ctime) where_is_object_time(scene, ob->track, ctime); solve_tracking (ob, ob->track->obmat); - } /* solve constraints */ if (ob->constraints.first) { bConstraintOb *cob; - cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); /* constraints need ctime, not stime. Some call where_is_object_time and bsystem_time */ solve_constraints (&ob->constraints, cob, ctime); @@ -1941,25 +1937,24 @@ void where_is_object_time(Object *ob, float ctime) else ob->transflag &= ~OB_NEG_SCALE; } -static void solve_parenting (Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul) +static void solve_parenting (Scene *scene, Object *ob, Object *par, float obmat[][4], float slowmat[][4], int simul) { float totmat[4][4]; float tmat[4][4]; float locmat[4][4]; float vec[3]; int ok; - + object_to_mat4(ob, locmat); if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, obmat); - switch(ob->partype & PARTYPE) { case PAROBJECT: ok= 0; if(par->type==OB_CURVE) { if( ((Curve *)par->data)->flag & CU_PATH ) { - ob_parcurve(ob, par, tmat); + ob_parcurve(scene, ob, par, tmat); ok= 1; } } @@ -2048,19 +2043,19 @@ void solve_tracking (Object *ob, float targetmat[][4]) } -void where_is_object(Object *ob) +void where_is_object(struct Scene *scene, Object *ob) { - where_is_object_time(ob, (float)G.scene->r.cfra); + where_is_object_time(scene, ob, (float)scene->r.cfra); } -void where_is_object_simul(Object *ob) +void where_is_object_simul(Scene *scene, Object *ob) /* was written for the old game engine (until 2.04) */ /* It seems that this function is only called for a lamp that is the child of another object */ { Object *par; - Ipo *ipo; + //Ipo *ipo; float *fp1, *fp2; float slowmat[4][4]; float fac1, fac2; @@ -2069,13 +2064,14 @@ for a lamp that is the child of another object */ /* NO TIMEOFFS */ /* no ipo! (because of dloc and realtime-ipos) */ - ipo= ob->ipo; - ob->ipo= NULL; + // XXX old animation system + //ipo= ob->ipo; + //ob->ipo= NULL; if(ob->parent) { par= ob->parent; - solve_parenting(ob, par, ob->obmat, slowmat, 1); + solve_parenting(scene, ob, par, ob->obmat, slowmat, 1); if(ob->partype & PARSLOW) { @@ -2100,45 +2096,47 @@ for a lamp that is the child of another object */ if (ob->constraints.first) { bConstraintOb *cob; - cob= constraints_make_evalob(ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - solve_constraints (&ob->constraints, cob, G.scene->r.cfra); + cob= constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + solve_constraints(&ob->constraints, cob, (float)scene->r.cfra); constraints_clear_evalob(cob); } /* WATCH IT!!! */ - ob->ipo= ipo; + // XXX old animation system + //ob->ipo= ipo; } /* for calculation of the inverse parent transform, only used for editor */ -void what_does_parent(Object *ob) +void what_does_parent(Scene *scene, Object *ob, Object *workob) { - clear_workob(); - Mat4One(workob.obmat); - Mat4One(workob.parentinv); - Mat4One(workob.constinv); - workob.parent= ob->parent; - workob.track= ob->track; + clear_workob(workob); + + Mat4One(workob->obmat); + Mat4One(workob->parentinv); + Mat4One(workob->constinv); + workob->parent= ob->parent; + workob->track= ob->track; - workob.trackflag= ob->trackflag; - workob.upflag= ob->upflag; + workob->trackflag= ob->trackflag; + workob->upflag= ob->upflag; - workob.partype= ob->partype; - workob.par1= ob->par1; - workob.par2= ob->par2; - workob.par3= ob->par3; + workob->partype= ob->partype; + workob->par1= ob->par1; + workob->par2= ob->par2; + workob->par3= ob->par3; - workob.constraints.first = ob->constraints.first; - workob.constraints.last = ob->constraints.last; + workob->constraints.first = ob->constraints.first; + workob->constraints.last = ob->constraints.last; - strcpy(workob.parsubstr, ob->parsubstr); + strcpy(workob->parsubstr, ob->parsubstr); - where_is_object(&workob); + where_is_object(scene, workob); } BoundBox *unit_boundbox() { BoundBox *bb; - float min[3] = {-1,-1,-1}, max[3] = {-1,-1,-1}; + float min[3] = {-1.0f,-1.0f,-1.0f}, max[3] = {-1.0f,-1.0f,-1.0f}; bb= MEM_callocN(sizeof(BoundBox), "bb"); boundbox_set_from_min_max(bb, min, max); @@ -2165,7 +2163,7 @@ BoundBox *object_get_boundbox(Object *ob) if(ob->type==OB_MESH) { bb = mesh_get_bb(ob); } - else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { + else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { bb= ( (Curve *)ob->data )->bb; } else if(ob->type==OB_MBALL) { @@ -2251,7 +2249,7 @@ void minmax_object(Object *ob, float *min, float *max) } /* TODO - use dupli objects bounding boxes */ -void minmax_object_duplis(Object *ob, float *min, float *max) +void minmax_object_duplis(Scene *scene, Object *ob, float *min, float *max) { if ((ob->transflag & OB_DUPLI)==0) { return; @@ -2259,7 +2257,7 @@ void minmax_object_duplis(Object *ob, float *min, float *max) ListBase *lb; DupliObject *dob; - lb= object_duplilist(G.scene, ob); + lb= object_duplilist(scene, ob); for(dob= lb->first; dob; dob= dob->next) { if(dob->no_draw); else { @@ -2279,13 +2277,16 @@ void minmax_object_duplis(Object *ob, float *min, float *max) /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */ /* requires flags to be set! */ -void object_handle_update(Object *ob) +void object_handle_update(Scene *scene, Object *ob) { if(ob->recalc & OB_RECALC) { - if(ob->recalc & OB_RECALC_OB) { - - // printf("recalcob %s\n", ob->id.name+2); + /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers, + which is only in where_is_object now */ + if(ob->recalc & OB_RECALC) { + + if (G.f & G_DEBUG) + printf("recalcob %s\n", ob->id.name+2); /* handle proxy copy for target */ if(ob->id.lib && ob->proxy_from) { @@ -2299,7 +2300,7 @@ void object_handle_update(Object *ob) Mat4CpyMat4(ob->obmat, ob->proxy_from->obmat); } else - where_is_object(ob); + where_is_object(scene, ob); #ifndef DISABLE_PYTHON if (G.f & G_DOSCRIPTLINKS) BPY_do_pyscript((ID *)ob, SCRIPT_OBJECTUPDATE); #endif @@ -2307,33 +2308,40 @@ void object_handle_update(Object *ob) if(ob->recalc & OB_RECALC_DATA) { - // printf("recalcdata %s\n", ob->id.name+2); + if (G.f & G_DEBUG) + printf("recalcdata %s\n", ob->id.name+2); /* includes all keys and modifiers */ if(ob->type==OB_MESH) { - makeDerivedMesh(ob, get_viewedit_datamask()); + EditMesh *em = BKE_mesh_get_editmesh(ob->data); + + // here was vieweditdatamask? XXX + if(ob==scene->obedit) { + makeDerivedMesh(scene, ob, em, CD_MASK_BAREMESH); + BKE_mesh_end_editmesh(ob->data, em); + } else + makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); } else if(ob->type==OB_MBALL) { - makeDispListMBall(ob); + makeDispListMBall(scene, ob); } else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - makeDispListCurveTypes(ob, 0); + makeDispListCurveTypes(scene, ob, 0); } - else if(ob->type==OB_LATTICE) { - lattice_calc_modifiers(ob); - } - else if(ob->type==OB_CAMERA) { - Camera *cam = (Camera *)ob->data; - calc_ipo(cam->ipo, frame_to_float(G.scene->r.cfra)); - execute_ipo(&cam->id, cam->ipo); + else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) { + ID *data_id= (ID *)ob->data; + AnimData *adt= BKE_animdata_from_id(data_id); + float ctime= (float)scene->r.cfra; // XXX this is bad... + + /* evaluate drivers */ + BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); } - else if(ob->type==OB_LAMP) { - Lamp *la = (Lamp *)ob->data; - calc_ipo(la->ipo, frame_to_float(G.scene->r.cfra)); - execute_ipo(&la->id, la->ipo); + else if(ob->type==OB_LATTICE) { + lattice_calc_modifiers(scene, ob); } else if(ob->type==OB_ARMATURE) { /* this happens for reading old files and to match library armatures with poses */ + // XXX this won't screw up the pose set already... if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) armature_rebuild_pose(ob, ob->data); @@ -2342,8 +2350,7 @@ void object_handle_update(Object *ob) // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); } else { - do_all_pose_actions(ob); - where_is_pose(ob); + where_is_pose(scene, ob); } } @@ -2354,7 +2361,7 @@ void object_handle_update(Object *ob) psys= ob->particlesystem.first; while(psys) { if(psys_check_enabled(ob, psys)) { - particle_system_update(ob, psys); + particle_system_update(scene, ob, psys); psys= psys->next; } else if(psys->flag & PSYS_DELETE) { @@ -2371,7 +2378,7 @@ void object_handle_update(Object *ob) /* this is to make sure we get render level duplis in groups: * the derivedmesh must be created before init_render_mesh, * since object_duplilist does dupliparticles before that */ - dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); + dm = mesh_create_derived_render(scene, ob, CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL); dm->release(dm); for(psys=ob->particlesystem.first; psys; psys=psys->next) @@ -2388,7 +2395,7 @@ void object_handle_update(Object *ob) /* set pointer in library proxy target, for copying, but restore it */ ob->proxy->proxy_from= ob; // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name); - object_handle_update(ob->proxy); + object_handle_update(scene, ob->proxy); } ob->recalc &= ~OB_RECALC; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index f6a65bd72a5..22e4e8a8309 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -61,7 +61,6 @@ #include "BKE_image.h" #include "BKE_font.h" #include "BKE_packedFile.h" -#include "BKE_bad_level_calls.h" /* <- waitcursor */ int seekPackedFile(PackedFile * pf, int offset, int whence) { @@ -180,7 +179,7 @@ PackedFile * newPackedFile(char * filename) char name[FILE_MAXDIR+FILE_MAXFILE]; void * data; - waitcursor(1); + //XXX waitcursor(1); // convert relative filenames to absolute filenames @@ -210,7 +209,7 @@ PackedFile * newPackedFile(char * filename) close(file); } - waitcursor(0); + //XXX waitcursor(0); return (pf); } @@ -283,7 +282,7 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode) char tempname[FILE_MAXDIR + FILE_MAXFILE]; /* void * data; */ - if (guimode) waitcursor(1); + if (guimode); //XXX waitcursor(1); strcpy(name, filename); BLI_convertstringcode(name, G.sce); @@ -306,28 +305,28 @@ int writePackedFile(char * filename, PackedFile *pf, int guimode) file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); if (file >= 0) { if (write(file, pf->data, pf->size) != pf->size) { - if(guimode) error("Error writing file: %s", name); + if(guimode) ; //XXX error("Error writing file: %s", name); ret_value = RET_ERROR; } close(file); } else { - if(guimode) error("Error creating file: %s", name); + if(guimode); //XXX error("Error creating file: %s", name); ret_value = RET_ERROR; } if (remove_tmp) { if (ret_value == RET_ERROR) { if (BLI_rename(tempname, name) != 0) { - if(guimode) error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + if(guimode); //XXX error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); } } else { if (BLI_delete(tempname, 0, 0) != 0) { - if(guimode) error("Error deleting '%s' (ignored)"); + if(guimode); //XXX error("Error deleting '%s' (ignored)"); } } } - if(guimode) waitcursor(0); + if(guimode); //XXX waitcursor(0); return (ret_value); } @@ -450,7 +449,7 @@ char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) break; } - how = pupmenu(menu); + //XXX how = pupmenu(menu); } switch (how) { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 3fea9e44acb..74a754c0ca8 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -46,7 +46,7 @@ #include "DNA_object_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" -#include "DNA_ipo_types.h" +#include "DNA_ipo_types.h" // XXX old animation system stuff to remove! #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -65,20 +65,17 @@ #include "BKE_displist.h" #include "BKE_particle.h" #include "BKE_DerivedMesh.h" -#include "BKE_ipo.h" #include "BKE_object.h" #include "BKE_softbody.h" #include "BKE_material.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_depsgraph.h" -#include "BKE_bad_level_calls.h" #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_cdderivedmesh.h" #include "BKE_pointcache.h" -#include "blendef.h" #include "RE_render_ext.h" static void key_from_object(Object *ob, ParticleKey *key); @@ -242,11 +239,11 @@ void psys_change_act(void *ob_v, void *act_v) npsys->flag |= PSYS_CURRENT; } } -Object *psys_get_lattice(Object *ob, ParticleSystem *psys) +Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { Object *lattice=0; - if(psys_in_edit_mode(psys)==0){ + if(psys_in_edit_mode(scene, psys)==0){ ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys); @@ -287,9 +284,9 @@ int psys_ob_has_hair(Object *ob) return 0; } -int psys_in_edit_mode(ParticleSystem *psys) +int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { - return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current(OBACT) && psys->edit); + return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current((scene->basact)->object) && psys->edit); } int psys_check_enabled(Object *ob, ParticleSystem *psys) { @@ -351,8 +348,19 @@ void free_hair(ParticleSystem *psys, int softbody) } void free_keyed_keys(ParticleSystem *psys) { - if(psys->particles && psys->particles->keys) + ParticleData *pa; + int i; + + if(psys->particles && psys->particles->keys) { MEM_freeN(psys->particles->keys); + + for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) { + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } + } + } } void free_child_path_cache(ParticleSystem *psys) { @@ -394,7 +402,8 @@ void psys_free(Object *ob, ParticleSystem * psys) free_keyed_keys(psys); - PE_free_particle_edit(psys); + if(psys->edit && psys->free_edit) + psys->free_edit(psys); if(psys->particles){ MEM_freeN(psys->particles); @@ -1410,6 +1419,7 @@ static float vert_weight(MDeformVert *dvert, int group) } return 0.0; } + static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, short type, short axis, float obmat[][4]) { float vec[3]={0.0,0.0,0.0}, q1[4]={1,0,0,0},q2[4]; @@ -1544,6 +1554,7 @@ static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, flo break; } } + static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump) { if(par && clumpfac!=0.0){ @@ -1561,7 +1572,8 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu VecLerpf(state->co,state->co,par->co,clump); } } -int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) + +int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb) { PartDeflect *pd; ParticleEffectorCache *ec; @@ -1644,7 +1656,7 @@ int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) /* curve taper */ if(cu->taperobj) - VecMulf(pa_loc,calc_taper(cu->taperobj,(int)(f_force*guidetime*100.0),100)); + VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100)); /* TODO */ //else{ ///* curve size*/ @@ -1719,7 +1731,7 @@ static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKe VECADD(state->co,state->co,rough); } -static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; @@ -1730,7 +1742,7 @@ static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleC QUATCOPY(eff_key.rot,(ca-1)->rot); pa= psys->particles+i; - do_effectors(i, pa, &eff_key, ob, psys, rootco, force, vel, dfra, cfra); + do_effectors(i, pa, &eff_key, scene, ob, psys, rootco, force, vel, dfra, cfra); VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); @@ -1738,12 +1750,12 @@ static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleC Normalize(force); + VECADDFAC(ca->co, (ca-1)->co, force, *length); + if(k < steps) { VecSubf(vec, (ca+1)->co, ca->co); *length = VecLength(vec); } - - VECADDFAC(ca->co, (ca-1)->co, force, *length); } static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec) { @@ -1856,20 +1868,20 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa VECCOPY(nor, vnor); } -int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) +int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) { ParticleThreadContext *ctx= threads[0].ctx; Object *ob= ctx->ob; ParticleSystem *psys= ctx->psys; ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; int steps = (int)pow(2.0,(double)part->draw_step); int totchild = psys->totchild; int i, seed, totthread= threads[0].tot; /*---start figuring out what is actually wanted---*/ - if(psys_in_edit_mode(psys)) + if(psys_in_edit_mode(scene, psys)) if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) totchild=0; @@ -1914,7 +1926,7 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) ctx->parent_pass= 0; ctx->cfra= cfra; - psys->lattice = psys_get_lattice(ob, psys); + psys->lattice = psys_get_lattice(scene, ob, psys); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ @@ -1929,10 +1941,12 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) } /* set correct ipo timing */ +#if 0 // XXX old animation system if(part->flag&PART_ABS_TIME && part->ipo){ calc_ipo(part->ipo, cfra); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system return 1; } @@ -2047,11 +2061,13 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, keys->steps = ctx->steps; /* correct child ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ float dsta=part->end-part->sta; calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0]))); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system /* get different child parameters from textures & vgroups */ ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); @@ -2133,7 +2149,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2161,7 +2177,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, /* apply different deformations to the child path */ if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide((ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + guided = do_guide(ctx->scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); if(guided==0){ if(part->kink) @@ -2278,7 +2294,7 @@ static void *exec_child_path_cache(void *data) return 0; } -void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) { ParticleSettings *part = psys->part; ParticleThread *pthreads; @@ -2287,9 +2303,9 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed ListBase threads; int i, totchild, totparent, totthread; - pthreads= psys_threads_create(ob, psys); + pthreads= psys_threads_create(scene, ob, psys); - if(!psys_threads_init_path(pthreads, cfra, editupdate)) { + if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { psys_threads_free(pthreads); return; } @@ -2344,11 +2360,11 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) { ParticleCacheKey *ca, **cache=psys->pathcache; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleEditSettings *pset = &scene->toolsettings->particle; ParticleSettings *part = psys->part; ParticleData *pa; @@ -2364,13 +2380,12 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda Material *ma; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = G.scene->r.frs_sec; + float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; float col[3] = {0.5f, 0.5f, 0.5f}; float prev_tangent[3], hairmat[4][4]; int k,i; int steps = (int)pow(2.0, (double)psys->part->draw_step); int totpart = psys->totpart; - char nosel[4], sel[4]; float sel_col[3]; float nosel_col[3]; float length, vec[3]; @@ -2382,25 +2397,25 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) return; - if(psys->renderdata) + if(psys->renderdata) { steps = (int)pow(2.0, (double)psys->part->ren_step); - else if(psys_in_edit_mode(psys)){ + } + else if(psys_in_edit_mode(scene, psys)) { edit=psys->edit; //timed = edit->draw_timed; - PE_get_colors(sel,nosel); - if(pset->brushtype == PE_BRUSH_WEIGHT){ + if(pset->brushtype == PE_BRUSH_WEIGHT) { sel_col[0] = sel_col[1] = sel_col[2] = 1.0f; nosel_col[0] = nosel_col[1] = nosel_col[2] = 0.0f; } else{ - sel_col[0] = (float)sel[0] / 255.0f; - sel_col[1] = (float)sel[1] / 255.0f; - sel_col[2] = (float)sel[2] / 255.0f; - nosel_col[0] = (float)nosel[0] / 255.0f; - nosel_col[1] = (float)nosel[1] / 255.0f; - nosel_col[2] = (float)nosel[2] / 255.0f; + sel_col[0] = (float)edit->sel_col[0] / 255.0f; + sel_col[1] = (float)edit->sel_col[1] / 255.0f; + sel_col[2] = (float)edit->sel_col[2] / 255.0f; + nosel_col[0] = (float)edit->nosel_col[0] / 255.0f; + nosel_col[1] = (float)edit->nosel_col[1] / 255.0f; + nosel_col[2] = (float)edit->nosel_col[2] / 255.0f; } } @@ -2420,7 +2435,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda soft= NULL; } - psys->lattice = psys_get_lattice(ob, psys); + psys->lattice = psys_get_lattice(scene, ob, psys); ma= give_current_material(ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) @@ -2613,16 +2628,16 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda for(k=0, ca=cache[i]; k<=steps; k++, ca++) { /* apply effectors */ if(!(psys->part->flag & PART_CHILD_EFFECT) && edit==0 && k) - do_path_effectors(ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); /* apply guide curves to path data */ if(edit==0 && psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) /* ca is safe to cast, since only co and vel are used */ - do_guide((ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); /* apply lattice */ if(psys->lattice && edit==0) - calc_latt_deform(ca->co, 1.0f); + calc_latt_deform(psys->lattice, ca->co, 1.0f); /* figure out rotation */ @@ -2702,8 +2717,8 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda psys->totcached = totpart; if(psys && psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(vg_effector) @@ -2957,7 +2972,9 @@ static void default_particle_settings(ParticleSettings *part) part->boidfac[i]=0.5; } +#if 0 // XXX old animation system part->ipo = NULL; +#endif // XXX old animation system part->simplify_refsize= 1920; part->simplify_rate= 1.0f; @@ -3046,46 +3063,26 @@ void make_local_particlesettings(ParticleSettings *part) } } -/* should be integrated to depgraph signals */ -void psys_flush_settings(ParticleSettings *part, int event, int hair_recalc) +void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc) { - Base *base; - Object *ob, *tob; + Base *base = scene->base.first; ParticleSystem *psys; int flush; - /* update all that have same particle settings */ - for(base = G.scene->base.first; base; base= base->next) { - if(base->object->particlesystem.first) { - ob=base->object; - flush=0; - for(psys=ob->particlesystem.first; psys; psys=psys->next){ - if(psys->part==part){ - psys->recalc |= event; - if(hair_recalc) - psys->recalc |= PSYS_RECALC_HAIR; - flush++; - } - else if(psys->part->type==PART_REACTOR){ - ParticleSystem *tpsys; - tob=psys->target_ob; - if(tob==0) - tob=ob; - tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - - if(tpsys && tpsys->part==part){ - psys->recalc |= event; - flush++; - } - } + for(base = scene->base.first; base; base = base->next) { + flush = 0; + for(psys = base->object->particlesystem.first; psys; psys=psys->next) { + if(psys->part == part) { + psys->recalc |= recalc; + flush++; } - if(flush) - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); } + if(flush) + DAG_object_flush_update(scene, base->object, OB_RECALC_DATA); } } -LinkNode *psys_using_settings(ParticleSettings *part, int flush_update) +LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update) { Object *ob, *tob; ParticleSystem *psys, *tpsys; @@ -3113,7 +3110,7 @@ LinkNode *psys_using_settings(ParticleSettings *part, int flush_update) } if(flush_update && found) - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } return node; @@ -3295,10 +3292,12 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, size=ptex.size; } +#if 0 // XXX old animation system if(icu_size){ calc_icu(icu_size,pa->time); size*=icu_size->curval; } +#endif // XXX old animation system if(vg_size) size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); @@ -3331,11 +3330,12 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) { ParticleSettings *part = psys->part; - float size, time; + float size; // time XXX if(part->childtype==PART_CHILD_FACES){ size=part->size; +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ IpoCurve *icu; @@ -3352,6 +3352,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, size = icu->curval; } } +#endif // XXX old animation system } else size=psys->particles[cpa->parent].size; @@ -3364,7 +3365,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, return size; } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ -void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) +void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) { ParticleSettings *part = psys->part; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); @@ -3376,7 +3377,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle HairKey *hkey[2] = {NULL, NULL}; ParticleKey *par=0, keys[4]; - float t, real_t, dfra, keytime, frs_sec = G.scene->r.frs_sec; + float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; float pa_clump = 0.0, pa_kink = 0.0; @@ -3387,7 +3388,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle float *cpa_fuv; int cpa_num; short cpa_from; - //if(psys_in_edit_mode(psys)){ + //if(psys_in_edit_mode(scene, psys)){ // if((psys->edit_path->flag & PSYS_EP_SHOW_CHILD)==0) // totchild=0; // edit=1; @@ -3471,7 +3472,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle } //} - //psys_get_particle_on_path(bsys,p,t,bkey,ckey[0]); + //psys_get_particle_on_path(scene, bsys,p,t,bkey,ckey[0]); //if(part->rotfrom==PART_ROT_KEYS) // QuatInterpol(state->rot,k2.rot,k3.rot,keytime); @@ -3509,12 +3510,12 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle Mat4Mul3Vecfl(hairmat, state->vel); if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(state, p, state->time, &psys->effectors); + do_guide(scene, state, p, state->time, &psys->effectors); /* TODO: proper velocity handling */ } if(psys->lattice && edit==0) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } } @@ -3539,7 +3540,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle /* get parent states */ while(w<4 && cpa->pa[w]>=0){ keys[w].time = t; - psys_get_particle_on_path(ob, psys, cpa->pa[w], keys+w, 1); + psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); w++; } @@ -3565,7 +3566,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle /* get the parent state */ keys->time = t; - psys_get_particle_on_path(ob,psys,cpa->parent,keys,1); + psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ pa=psys->particles+cpa->parent; @@ -3578,11 +3579,13 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle } /* correct child ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ calc_ipo(part->ipo, 100.0f*t); execute_ipo((ID *)part, part->ipo); } - +#endif // XXX old animation system + /* get different child parameters from textures & vgroups */ ptex.clump=1.0; ptex.kink=1.0; @@ -3651,19 +3654,19 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle //if(vel){ // if(t>=0.001f){ // tstate.time=t-0.001f; - // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); // VECSUB(state->vel,state->co,tstate.co); // } // else{ // tstate.time=t+0.001f; - // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); // VECSUB(state->vel,tstate.co,state->co); // } //} } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ -int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ +int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ ParticleSettings *part=psys->part; ParticleData *pa=0; float cfra; @@ -3673,7 +3676,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey if(state->time>0) cfra=state->time; else - cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0); + cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0); if(psys->totchild && p>=totpart){ if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ @@ -3709,7 +3712,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey else state->time= (cfra-pa->time)/(pa->dietime-pa->time); - psys_get_particle_on_path(ob,psys,p,state,1); + psys_get_particle_on_path(scene, ob, psys, p, state,1); return 1; } else{ @@ -3741,7 +3744,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ @@ -3753,7 +3756,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey /* let's interpolate to try to be as accurate as possible */ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { ParticleKey keys[4]; - float dfra, keytime, frs_sec = G.scene->r.frs_sec; + float dfra, keytime, frs_sec = scene->r.frs_sec; if(pa->prev_state.time >= pa->state.time) { /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ @@ -3793,7 +3796,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey } if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } @@ -3974,4 +3977,5 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] VECADDFAC(center, bb->vec, xvec, bb->offset[0]); VECADDFAC(center, center, yvec, bb->offset[1]); -}
\ No newline at end of file +} + diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bbf62d033bf..c0ef92b489e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -42,11 +42,11 @@ #include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_material_types.h" -#include "DNA_ipo_types.h" #include "DNA_curve_types.h" #include "DNA_group_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed! #include "BLI_rand.h" #include "BLI_jitter.h" @@ -58,7 +58,6 @@ #include "BLI_threads.h" #include "BKE_anim.h" -#include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" #include "BKE_collision.h" #include "BKE_displist.h" @@ -69,7 +68,6 @@ #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" -#include "BKE_ipo.h" #include "BKE_softbody.h" #include "BKE_depsgraph.h" #include "BKE_lattice.h" @@ -81,17 +79,12 @@ #include "PIL_time.h" -#include "BSE_headerbuttons.h" - -#include "blendef.h" - #include "RE_shader_ext.h" /* fluid sim particle import */ #ifndef DISABLE_ELBEEM #include "DNA_object_fluidsim.h" #include "LBM_fluidsim.h" -#include "elbeem.h" #include <zlib.h> #include <string.h> @@ -203,8 +196,11 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(psys->particles->keys) MEM_freeN(psys->particles->keys); - for(i=0, pa=psys->particles; i<totsaved; i++, pa++) - if(pa->keys) pa->keys= NULL; + for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++) if(pa->hair) MEM_freeN(pa->hair); @@ -222,7 +218,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) psys->totpart=totpart; } -static int get_psys_child_number(ParticleSystem *psys) +static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys) { int nbr; @@ -231,15 +227,15 @@ static int get_psys_child_number(ParticleSystem *psys) if(psys->renderdata) { nbr= psys->part->ren_child_nbr; - return get_render_child_particle_number(&G.scene->r, nbr); + return get_render_child_particle_number(&scene->r, nbr); } else return psys->part->child_nbr; } -static int get_psys_tot_child(ParticleSystem *psys) +static int get_psys_tot_child(struct Scene *scene, ParticleSystem *psys) { - return psys->totpart*get_psys_child_number(psys); + return psys->totpart*get_psys_child_number(scene, psys); } static void alloc_child_particles(ParticleSystem *psys, int tot) @@ -935,7 +931,7 @@ static int compare_orig_index(const void *p1, const void *p2) /* 6. and we're done! */ /* This is to denote functionality that does not yet work with mesh - only derived mesh */ -int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm, int from) +int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) { ParticleThreadContext *ctx= threads[0].ctx; Object *ob= ctx->ob; @@ -966,7 +962,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm return 0; if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) { - error("Can't paint with the current modifier stack, disable destructive modifiers"); +// XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); return 0; } @@ -988,7 +984,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm BLI_kdtree_balance(tree); - totpart=get_psys_tot_child(psys); + totpart=get_psys_tot_child(scene, psys); cfrom=from=PART_FROM_FACE; if(part->flag&PART_CHILD_SEAMS){ @@ -1037,9 +1033,9 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm } else{ /* no need to figure out distribution */ - int child_nbr= get_psys_child_number(psys); + int child_nbr= get_psys_child_number(scene, psys); - totpart= get_psys_tot_child(psys); + totpart= get_psys_tot_child(scene, psys); alloc_child_particles(psys, totpart); cpa=psys->child; for(i=0; i<child_nbr; i++){ @@ -1372,16 +1368,16 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm return 1; } -static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Object *ob, ParticleSystem *psys, int from) { ListBase threads; ParticleThread *pthreads; ParticleThreadContext *ctx; int i, totthread; - pthreads= psys_threads_create(ob, psys); + pthreads= psys_threads_create(scene, ob, psys); - if(!psys_threads_init_distribution(pthreads, finaldm, from)) { + if(!psys_threads_init_distribution(pthreads, scene, finaldm, from)) { psys_threads_free(pthreads); return; } @@ -1421,7 +1417,7 @@ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int pa->num= -1; } } -static void distribute_particles(Object *ob, ParticleSystem *psys, int from) +static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, int from) { ParticleSystemModifierData *psmd=0; int distr_error=0; @@ -1429,7 +1425,7 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from) if(psmd){ if(psmd->dm) - distribute_particles_on_dm(psmd->dm,ob,psys,from); + distribute_particles_on_dm(psmd->dm, scene, ob, psys, from); else distr_error=1; } @@ -1451,20 +1447,21 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from) } /* threaded child particle distribution and path caching */ -ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys) +ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys) { ParticleThread *threads; ParticleThreadContext *ctx; int i, totthread; - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; + if(scene->r.mode & R_FIXED_THREADS) + totthread= scene->r.threads; else totthread= BLI_system_thread_count(); threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); + ctx->scene= scene; ctx->ob= ob; ctx->psys= psys; ctx->psmd= psys_get_modifier(ob, psys); @@ -1502,8 +1499,8 @@ void psys_threads_free(ParticleThread *threads) MEM_freeN(ctx->vg_roughe); if(ctx->psys->lattice){ - end_latt_deform(); - ctx->psys->lattice=0; + end_latt_deform(ctx->psys->lattice); + ctx->psys->lattice= NULL; } /* distribution */ @@ -1534,7 +1531,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps ParticleSettings *part; ParticleTexture ptex; Material *ma=0; - IpoCurve *icu=0; + //IpoCurve *icu=0; // XXX old animation system int totpart; float rand,length; @@ -1557,9 +1554,9 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps pa->lifetime= part->lifetime*ptex.life; if(part->type==PART_HAIR) - pa->time=0.0f; + pa->time= 0.0f; else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - pa->time=MAXFRAMEF; + pa->time= 300000.0f; /* max frame */ else{ //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); //if(icu){ @@ -1575,13 +1572,15 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps pa->lifetime=100.0f; } else{ +#if 0 // XXX old animation system icu=find_ipocurve(psys->part->ipo,PART_EMIT_LIFE); if(icu){ calc_icu(icu,100*ptex.time); pa->lifetime*=icu->curval; } +#endif // XXX old animation system - /* need to get every rand even if we don't use them so that randoms don't affect eachother */ + /* need to get every rand even if we don't use them so that randoms don't affect each other */ rand= BLI_frand(); if(part->randlife!=0.0) pa->lifetime*= 1.0f - part->randlife*rand; @@ -1632,7 +1631,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps } static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) { - IpoCurve *icu=0; + //IpoCurve *icu=0; // XXX old animation system ParticleData *pa; int p, totpart=psys->totpart; @@ -1640,6 +1639,7 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS initialize_particle(pa,p,ob,psys,psmd); if(psys->part->type != PART_FLUID) { +#if 0 // XXX old animation system icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ); if(icu){ float time=psys->part->sta, end=psys->part->end; @@ -1648,6 +1648,7 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS p=0; pa=psys->particles; + calc_icu(icu,time); v1=icu->curval; if(v1<0.0f) v1=0.0f; @@ -1688,16 +1689,17 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS pa->flag |= PARS_UNEXIST; } } +#endif // XXX old animation system } } /* sets particle to the emitter surface with initial velocity & rotation */ -void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob, +void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot) { ParticleSettings *part; ParticleTexture ptex; ParticleKey state; - IpoCurve *icu=0; + //IpoCurve *icu=0; // XXX old animation system float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; @@ -1721,7 +1723,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi if(pa->num == -1) memset(&state, 0, sizeof(state)); else - psys_get_particle_state(tob,tpsys,pa->num,&state,1); + psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1); psys_get_from_key(&state,loc,nor,rot,0); QuatMulVecf(rot,vtan); @@ -1742,7 +1744,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi else{ /* get precise emitter matrix if particle is born */ if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= psys->cfra) - where_is_object_time(ob,pa->time); + where_is_object_time(scene, ob,pa->time); /* get birth location from object */ psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); @@ -1842,11 +1844,13 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi if(part->partfac!=0.0) VECADDFAC(vel,vel,p_vel,part->partfac); +#if 0 // XXX old animation system icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL); if(icu){ calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); ptex.ivel*=icu->curval; } +#endif // XXX old animation system VecMulf(vel,ptex.ivel); @@ -1916,11 +1920,13 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi Normalize(pa->state.ave); VecMulf(pa->state.ave,part->avefac); +#if 0 // XXX old animation system icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE); if(icu){ calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta))); VecMulf(pa->state.ave,icu->curval); } +#endif // XXX old animation system } pa->dietime = pa->time + pa->lifetime; @@ -1933,7 +1939,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi pa->stick_ob = 0; pa->flag &= ~PARS_STICKY; } -static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) +static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) { ParticleData *pa; int p, totpart=psys->totpart; @@ -1942,7 +1948,7 @@ static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystem float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); for(p=from, pa=psys->particles+from; p<totpart; p++, pa++) - reset_particle(pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot); + reset_particle(scene, pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot); if(vg_vel) MEM_freeN(vg_vel); @@ -2002,12 +2008,11 @@ int psys_count_keyed_targets(Object *ob, ParticleSystem *psys) return select; } -static void set_keyed_keys(Object *ob, ParticleSystem *psys) +static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) { Object *kob = ob; ParticleSystem *kpsys = psys; ParticleData *pa; - ParticleKey state; int totpart = psys->totpart, i, k, totkeys = psys->totkeyed + 1; float prevtime, nexttime, keyedtime; @@ -2031,12 +2036,13 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys) } psys->flag &= ~PSYS_KEYED; - state.time=-1.0; for(k=0; k<totkeys; k++) { for(i=0,pa=psys->particles; i<totpart; i++, pa++) { + (pa->keys + k)->time = -1.0; /* use current time */ + if(kpsys->totpart > 0) - psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); + psys_get_particle_state(scene, kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); if(k==0) pa->keys->time = pa->time; @@ -2300,7 +2306,7 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, VecAddf(field,field,mag_vec); } -static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSystem *psys) +static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys) { ParticleEffectorCache *ec; PartDeflect *pd= ob->pd; @@ -2312,7 +2318,7 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy Curve *cu= ob->data; if(cu->flag & CU_PATH) { if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(ob, 0); + makeDispListCurveTypes(scene, ob, 0); if(cu->path && cu->path->data) { type |= PSYS_EC_EFFECTOR; } @@ -2383,7 +2389,7 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy } } -static void psys_init_effectors_recurs(Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level) +static void psys_init_effectors_recurs(Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level) { Group *group; GroupObject *go; @@ -2393,17 +2399,17 @@ static void psys_init_effectors_recurs(Object *ob, Object *obsrc, ParticleSystem if(ob->lay & layer) { if(ob->pd || ob->particlesystem.first) - add_to_effectors(listb, ob, obsrc, psys); + add_to_effectors(listb, scene, ob, obsrc, psys); if(ob->dup_group) { group= ob->dup_group; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(go->ob, obsrc, psys, listb, level+1); + psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, level+1); } } } -void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys) +void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSystem *psys) { ListBase *listb= &psys->effectors; Base *base; @@ -2414,11 +2420,11 @@ void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys) GroupObject *go; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(go->ob, obsrc, psys, listb, 0); + psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, 0); } else { - for(base = G.scene->base.first; base; base= base->next) - psys_init_effectors_recurs(base->object, obsrc, psys, listb, 0); + for(base = scene->base.first; base; base= base->next) + psys_init_effectors_recurs(scene, base->object, obsrc, psys, listb, 0); } } @@ -2454,7 +2460,7 @@ void psys_end_effectors(ParticleSystem *psys) } } -static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -2518,7 +2524,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo ec->tree=tree; for(p=0, epa=epsys->particles; p<totepart; p++,epa++) - if(epa->alive==PARS_ALIVE && psys_get_particle_state(eob,epsys,p,&state,0)) + if(epa->alive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0)) BLI_kdtree_insert(tree, p, state.co, NULL); BLI_kdtree_balance(tree); @@ -2536,7 +2542,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo /* calculate forces that all effectors apply to a particle*/ -void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra) +void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra) { Object *eob; ParticleSystem *epsys; @@ -2570,7 +2576,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P if(ec->type & PSYS_EC_EFFECTOR){ pd=eob->pd; if(psys->part->type!=PART_HAIR && psys->part->integrator) - where_is_object_time(eob,cfra); + where_is_object_time(scene, eob,cfra); if(pd && pd->flag&PFIELD_SURFACE) { surmd = (SurfaceModifierData *)modifiers_findByType ( eob, eModifierType_Surface ); @@ -2611,7 +2617,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat, pd->f_strength, falloff, force_field); } else { - do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, + do_physical_effector(scene, eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } @@ -2635,7 +2641,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P p=0; } - epsys->lattice=psys_get_lattice(ob,psys); + epsys->lattice= psys_get_lattice(scene, ob, psys); for(; p<totepart; p++){ /* particle skips itself as effector */ @@ -2643,7 +2649,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P epa = epsys->particles + p; estate.time=cfra; - if(psys_get_particle_state(eob,epsys,p,&estate,0)){ + if(psys_get_particle_state(scene, eob,epsys,p,&estate,0)){ VECSUB(vec_to_part, state->co, estate.co); distance = VecLength(vec_to_part); @@ -2655,22 +2661,22 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P if(falloff<=0.0f) ; /* don't do anything */ else - do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, + do_physical_effector(scene, eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); } } else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ - psys_get_particle_state(eob,epsys,p,&estate,1); + psys_get_particle_state(scene, eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); /* TODO: add rotation handling here too */ } } if(epsys->lattice){ - end_latt_deform(); - epsys->lattice=0; + end_latt_deform(epsys->lattice); + epsys->lattice= NULL; } } } @@ -2681,7 +2687,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) +static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) { ParticleKey states[5], tkey; float force[3],tvel[3],dx[4][3],dv[4][3]; @@ -2713,7 +2719,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti tvel[0]=tvel[1]=tvel[2]=0.0; /* add effectors */ if(part->type != PART_HAIR) - do_effectors(pa_no,pa,states+i,ob,psys,states->co,force,tvel,dfra,fra); + do_effectors(pa_no,pa,states+i,scene, ob, psys,states->co,force,tvel,dfra,fra); /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ @@ -2817,7 +2823,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti tkey.time=pa->state.time; if(part->type != PART_HAIR) { - if(do_guide(&tkey,pa_no,time,&psys->effectors)) { + if(do_guide(scene, &tkey, pa_no, time, &psys->effectors)) { VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); @@ -2882,7 +2888,7 @@ static void intersect_dm_quad_weights(float *v1, float *v2, float *v3, float *v4 } /* check intersection with a derivedmesh */ -int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_w, +int psys_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_w, float *face_minmax, float *pa_minmax, float radius, float *ipoint) { MFace *mface=0; @@ -2894,9 +2900,9 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, if(dm==0){ psys_disable_all(ob); - dm=mesh_get_derived_final(ob,0); + dm=mesh_get_derived_final(scene, ob, 0); if(dm==0) - dm=mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_deform(scene, ob, 0); psys_enable_all(ob); @@ -3094,7 +3100,7 @@ static void particle_intersect_face(void *userdata, int index, const BVHTreeRay /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ +static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ Object *ob = NULL; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -3127,7 +3133,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part ob= ec->ob; if(part->type!=PART_HAIR) - where_is_object_time(ob,cfra); + where_is_object_time(scene, ob,cfra); /* particles should not collide with emitter at birth */ if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) @@ -3299,7 +3305,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /************************************************/ /* Boid physics */ /************************************************/ -static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float *vec1, float *vec2, float *loc, float *nor, float cfra) +static int boid_see_mesh(ListBase *lb, Scene *scene, Object *pob, ParticleSystem *psys, float *vec1, float *vec2, float *loc, float *nor, float cfra) { Object *ob, *min_ob; DerivedMesh *dm; @@ -3320,7 +3326,7 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float ob= ec->ob; if(psys->part->type!=PART_HAIR) - where_is_object_time(ob,cfra); + where_is_object_time(scene, ob,cfra); if(ob==pob) dm=psmd->dm; @@ -3338,7 +3344,7 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float Mat4MulVecfl(imat,co2); } - if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w,ec->face_minmax,0,0,0)) + if(psys_intersect_dm(scene,ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w,ec->face_minmax,0,0,0)) min_ob=ob; } } @@ -3351,9 +3357,9 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float else{ psys_disable_all(ob); - dm=mesh_get_derived_final(ob,0); + dm=mesh_get_derived_final(scene, ob, 0); if(dm==0) - dm=mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_deform(scene, ob, 0); psys_enable_all(ob); } @@ -3456,7 +3462,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l } } /* determines the acceleration that the boid tries to acchieve */ -static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) +static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) { ParticleData *pars=psys->particles; KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1]; @@ -3490,7 +3496,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS bvf->Copyf(dvec,pa->prev_state.vel); bvf->Mulf(dvec,5.0f); bvf->Addf(dvec,dvec,pa->prev_state.co); - if(boid_see_mesh(&psys->effectors,ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){ + if(boid_see_mesh(&psys->effectors,scene, ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){ float probelen = bvf->Length(dvec); float proj; float oblen; @@ -3556,7 +3562,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; p<count; p++){ state.time=-1.0; - if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){ + if(psys_get_particle_state(scene, eob,epsys,ptn2[p].index,&state,0)){ VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3703,7 +3709,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; p<count; p++){ state.time=-1.0; - if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){ + if(psys_get_particle_state(scene, eob,epsys,ptn2[p].index,&state,0)){ VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3736,7 +3742,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } } /* tries to realize the wanted acceleration */ -static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc) +static void boid_body(Scene *scene, BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc) { float dvec[3], bvec[3], length, max_vel=part->max_vel; float q2[4], q[4]; @@ -3863,14 +3869,14 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, Mat4MulVecfl(imat,co1); Mat4MulVecfl(imat,co2); - if(psys_intersect_dm(zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){ + if(psys_intersect_dm(scene,zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){ DerivedMesh *dm; MFace *mface; MVert *mvert; float loc[3],nor[3],q1[4]; psys_disable_all(zob); - dm=mesh_get_derived_final(zob,0); + dm=mesh_get_derived_final(scene, zob, 0); psys_enable_all(zob); mface=dm->getFaceDataArray(dm,CD_MFACE); @@ -3912,7 +3918,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, /************************************************/ /* Hair */ /************************************************/ -static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ +static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ ParticleData *pa; HairKey *key; int totpart; @@ -3920,7 +3926,7 @@ static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierDa Mat4Invert(ob->imat,ob->obmat); - psys->lattice=psys_get_lattice(ob,psys); + psys->lattice= psys_get_lattice(scene, ob, psys); if(psys->totpart==0) return; @@ -3960,19 +3966,19 @@ static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierDa /* System Core */ /************************************************/ /* unbaked particles are calculated dynamically */ -static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, +static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) { ParticleData *pa; ParticleSettings *part=psys->part; KDTree *tree=0; BoidVecFunc bvf; - IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); + IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); float timestep; int p, totpart; /* current time */ - float ctime, ipotime; + float ctime, ipotime; // XXX old animation system /* frame & time changes */ float dfra, dtime, pa_dtime, pa_dfra=0.0; float birthtime, dietime; @@ -3985,12 +3991,14 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi timestep=psys_get_timestep(part); dtime= dfra*timestep; ctime= cfra*timestep; - ipotime= cfra; + ipotime= cfra; // XXX old animation system +#if 0 // XXX old animation system if(part->flag&PART_ABS_TIME && part->ipo){ calc_ipo(part->ipo, cfra); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system if(dfra<0.0){ float *vg_size=0; @@ -4001,14 +4009,16 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi if(pa->flag & PARS_UNEXIST) continue; /* set correct ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ ipotime=100.0f*(cfra-pa->time)/pa->lifetime; calc_ipo(part->ipo, ipotime); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); - reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); if(cfra>pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ pa->loop=(short)((cfra-pa->time)/pa->lifetime); @@ -4038,10 +4048,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi if(psys->effectors.first) psys_end_effectors(psys); - psys_init_effectors(ob,part->eff_group,psys); + psys_init_effectors(scene, ob, part->eff_group, psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(scene, ob,psys,psmd,cfra); if(part->phystype==PART_PHYS_BOIDS){ /* create particle tree for fast inter-particle comparisons */ @@ -4063,11 +4073,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ ipotime=100.0f*(cfra-pa->time)/pa->lifetime; calc_ipo(part->ipo, ipotime); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); /* reactions can change birth time so they need to be checked first */ @@ -4082,7 +4094,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ - reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); } pa_dfra = dfra; @@ -4109,10 +4121,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ - apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra); + apply_particle_forces(scene, p, pa, ob, psys, part, timestep,pa_dfra,cfra); /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + deflect_particle(scene, ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); /* rotations */ rotate_particle(part,pa,pa_dfra,timestep); @@ -4120,9 +4132,9 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi case PART_PHYS_BOIDS: { float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); + boid_brain(&bvf, pa, scene, ob, psys, part, tree, timestep,cfra,acc); if(pa->alive != PARS_DYING) - boid_body(&bvf,pa,psys,part,timestep,acc); + boid_body(scene, &bvf,pa,psys,part,timestep,acc); break; } } @@ -4132,7 +4144,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi if(part->flag & PART_LOOP && part->type!=PART_HAIR){ pa->loop++; - reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(scene, pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); pa->alive=PARS_ALIVE; } else{ @@ -4158,26 +4170,26 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } /* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&G.scene->toolsettings->particle; + ParticleEditSettings *pset=&scene->toolsettings->particle; int distr=0,alloc=0; - if((psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) || psys->recalc&PSYS_ALLOC) + if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) + if(alloc || psys->recalc&PSYS_RECALC_RESET || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT))) distr=1; if(distr){ if(alloc) realloc_particles(ob,psys,psys->totpart); - if(get_psys_tot_child(psys)) { + if(get_psys_tot_child(scene, psys)) { /* don't generate children while computing the hair keys */ if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(ob,psys,PART_FROM_CHILD); + distribute_particles(scene, ob, psys, PART_FROM_CHILD); if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) psys_find_parents(ob,psmd,psys); @@ -4185,22 +4197,47 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, } } - if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && (psys_in_edit_mode(psys) - || (part->type==PART_HAIR || part->draw_as==PART_DRAW_PATH))){ - psys_cache_paths(ob, psys, cfra, 0); + if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR + || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ + + psys_cache_paths(scene, ob, psys, cfra, 0); /* for render, child particle paths are computed on the fly */ if(part->childtype) { - if(((psys->totchild!=0)) || (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD))) + if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_SHOW_CHILD))) if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) - psys_cache_child_paths(ob, psys, cfra, 0); + psys_cache_child_paths(scene, ob, psys, cfra, 0); } } else if(psys->pathcache) psys_free_path_cache(psys); } -static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +/* calculate and store key locations in world coordinates */ +void psys_update_world_cos(Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + ParticleData *pa; + ParticleEditKey *key; + int i, k, totpart; + float hairmat[4][4]; + + if(psys==0 || psys->edit==0) + return; + + totpart= psys->totpart; + + for(i=0, pa=psys->particles; i<totpart; i++, pa++) { + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + + for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) { + VECCOPY(key->world_co,key->co); + Mat4MulVecfl(hairmat, key->world_co); + } + } +} + +static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part = psys->part; ParticleData *pa; @@ -4214,33 +4251,33 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst pa->flag &= ~PARS_NO_DISP; } - if(psys->recalc & PSYS_DISTR) + if(psys->recalc & PSYS_RECALC_RESET) /* need this for changing subsurf levels */ psys_calc_dmcache(ob, psmd->dm, psys); if(psys->effectors.first) psys_end_effectors(psys); - psys_init_effectors(ob,part->eff_group,psys); + psys_init_effectors(scene, ob, part->eff_group, psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(scene, ob,psys,psmd,cfra); - if(psys_in_edit_mode(psys)) - PE_recalc_world_cos(ob, psys); + if(psys_in_edit_mode(scene, psys)) + psys_update_world_cos(ob, psys); - psys_update_path_cache(ob,psmd,psys,cfra); + psys_update_path_cache(scene, ob,psmd,psys,cfra); } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part=psys->part; ParticleData *pa; ParticleKey state; - IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); + IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); int p; - float ipotime=cfra, disp, birthtime, dietime, *vg_size= NULL; + float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra if(part->from!=PART_FROM_PARTICLE) vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); @@ -4249,22 +4286,24 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy psys_end_effectors(psys); //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ - psys_init_effectors(ob,part->eff_group,psys); + psys_init_effectors(scene, ob, part->eff_group, psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(scene, ob,psys,psmd,cfra); //} disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ ipotime=100.0f*(cfra-pa->time)/pa->lifetime; calc_ipo(part->ipo, ipotime); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); - psys->lattice=psys_get_lattice(ob,psys); + psys->lattice= psys_get_lattice(scene, ob, psys); if(part->flag & PART_LOOP && part->type!=PART_HAIR) pa->loop = (short)((cfra - pa->time) / pa->lifetime); @@ -4280,7 +4319,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy else if(dietime <= cfra){ if(dietime > psys->cfra){ state.time = pa->dietime; - psys_get_particle_state(ob,psys,p,&state,1); + psys_get_particle_state(scene, ob,psys,p,&state,1); push_reaction(ob,psys,p,PART_EVENT_DEATH,&state); } pa->alive = PARS_DEAD; @@ -4288,14 +4327,14 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy else{ pa->alive = PARS_ALIVE; state.time = cfra; - psys_get_particle_state(ob,psys,p,&state,1); + psys_get_particle_state(scene, ob,psys,p,&state,1); state.time = cfra; push_reaction(ob,psys,p,PART_EVENT_NEAR,&state); } if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(pa->r_rot[0] > disp) @@ -4305,9 +4344,9 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy } /* make sure that children are up to date */ - if(psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) { + if(psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) { realloc_particles(ob, psys, psys->totpart); - distribute_particles(ob, psys, PART_FROM_CHILD); + distribute_particles(scene, ob, psys, PART_FROM_CHILD); } if(vg_size) @@ -4332,23 +4371,21 @@ void psys_changed_type(ParticleSystem *psys) psys->flag &= ~PSYS_KEYED; if(part->type == PART_HAIR) { - part->draw_as = PART_DRAW_PATH; - part->rotfrom = PART_ROT_IINCR; - } - else { - free_hair(psys, 1); + if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) + part->ren_as = PART_DRAW_PATH; - if(part->draw_as == PART_DRAW_PATH) - if(psys->part->phystype != PART_PHYS_KEYED) - part->draw_as = PART_DRAW_DOT; + if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) + part->draw_as = PART_DRAW_REND; } + else + free_hair(psys, 1); psys->softflag= 0; psys_reset(psys, PSYS_RESET_ALL); } -static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) +static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra) { if(psys->particles){ MEM_freeN(psys->particles); @@ -4369,13 +4406,13 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) char *suffix2 = ".gz"; char filename[256]; char debugStrBuffer[256]; - int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading + int curFrame = scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading int p, j, numFileParts, totpart; int readMask, activeParts = 0, fileParts = 0; gzFile gzf; - if(ob==G.obedit) // off... - return; +// XXX if(ob==G.obedit) // off... +// return; // ok, start loading strcpy(filename, fss->surfdataPath); @@ -4387,7 +4424,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) gzf = gzopen(filename, "rb"); if (!gzf) { snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); - //elbeemDebugOut(debugStrBuffer); + // XXX bad level call elbeemDebugOut(debugStrBuffer); return; } @@ -4397,7 +4434,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) part->totpart= totpart; part->sta=part->end = 1.0f; - part->lifetime = G.scene->r.efra + 1; + part->lifetime = scene->r.efra + 1; /* initialize particles */ realloc_particles(ob, psys, part->totpart); @@ -4447,7 +4484,9 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) totpart = psys->totpart = activeParts; snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d \n", psys->totpart,activeParts,fileParts,readMask); - elbeemDebugOut(debugStrBuffer); + // bad level call + // XXX elbeemDebugOut(debugStrBuffer); + } // fluid sim particles done } #endif // DISABLE_ELBEEM @@ -4455,7 +4494,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) /* Calculates the next state for all particles of the system */ /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/ -static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ParticleSettings *part; ParticleData *pa; @@ -4469,28 +4508,30 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier part= psys->part; cache= psys->pointcache; - framenr= (int)CFRA; + framenr= (int)scene->r.cfra; framedelta= framenr - cache->simframe; BKE_ptcache_id_from_particles(&pid, ob, psys); - BKE_ptcache_id_time(&pid, 0.0f, &startframe, &endframe, NULL); + BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); /* update ipo's */ +#if 0 // XXX old animation system if((part->flag & PART_ABS_TIME) && part->ipo) { calc_ipo(part->ipo, cfra); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system /* hair if it's already done is handled separate */ if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) { - hair_step(ob, psmd, psys, cfra); + hair_step(scene, ob, psmd, psys, cfra); psys->cfra = cfra; psys->recalc = 0; return; } /* fluid is also handled separate */ else if(part->type == PART_FLUID) { - particles_fluid_step(ob, psys, framenr); + particles_fluid_step(scene, ob, psys, framenr); psys->cfra = cfra; psys->recalc = 0; return; @@ -4525,7 +4566,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; - totchild = get_psys_tot_child(psys); + totchild = get_psys_tot_child(scene, psys); if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) { only_children_changed = (oldtotpart == totpart); @@ -4535,7 +4576,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier init= 1; } - if(psys->recalc & PSYS_DISTR) { + if(psys->recalc & PSYS_RECALC_RESET) { distr= 1; init= 1; } @@ -4545,20 +4586,22 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(alloc) realloc_particles(ob, psys, totpart); - distribute_particles(ob, psys, part->from); + distribute_particles(scene, ob, psys, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ psys_free_children(psys); - else if(get_psys_tot_child(psys)) - distribute_particles(ob, psys, PART_FROM_CHILD); + else if(get_psys_tot_child(scene, psys)) + distribute_particles(scene, ob, psys, PART_FROM_CHILD); } if(only_children_changed==0) { + free_keyed_keys(psys); + initialize_all_particles(ob, psys, psmd); if(alloc) - reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart); + reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart); } /* flag for possible explode modifiers after this system */ @@ -4570,15 +4613,15 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(get_particles_from_cache(ob, psys, framenr)) { if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { psys_count_keyed_targets(ob,psys); - set_keyed_keys(ob, psys); + set_keyed_keys(scene, ob, psys); } - cached_step(ob,psmd,psys,cfra); + cached_step(scene, ob, psmd, psys, cfra); psys->cfra=cfra; psys->recalc = 0; if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { - psys_update_path_cache(ob,psmd,psys,framenr); + psys_update_path_cache(scene, ob, psmd, psys, framenr); } cache->simframe= framenr; @@ -4640,7 +4683,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier for(dframe=-totframesback; dframe<=0; dframe++) { /* ok now we're all set so let's go */ - dynamics_step(ob,psys,psmd,cfra+dframe,vg_vel,vg_tan,vg_rot,vg_size); + dynamics_step(scene, ob, psys, psmd, cfra+dframe, vg_vel, vg_tan, vg_rot, vg_size); psys->cfra = cfra+dframe; } } @@ -4657,8 +4700,8 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED){ - set_keyed_keys(ob, psys); - psys_update_path_cache(ob,psmd,psys,(int)cfra); + set_keyed_keys(scene, ob, psys); + psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); } else if(psys->pathcache) psys_free_path_cache(psys); @@ -4670,12 +4713,12 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(vg_size) MEM_freeN(vg_size); if(psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } } -static void psys_to_softbody(Object *ob, ParticleSystem *psys) +static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys) { SoftBody *sb; short softflag; @@ -4695,7 +4738,7 @@ static void psys_to_softbody(Object *ob, ParticleSystem *psys) ob->softflag= psys->softflag; /* do softbody */ - sbObjectStep(ob, (float)G.scene->r.cfra, NULL, psys_count_keys(psys)); + sbObjectStep(scene, ob, (float)scene->r.cfra, NULL, psys_count_keys(psys)); /* return things back to normal */ psys->soft= ob->soft; @@ -4708,8 +4751,8 @@ static void psys_to_softbody(Object *ob, ParticleSystem *psys) static int hair_needs_recalc(ParticleSystem *psys) { if((psys->flag & PSYS_EDITED)==0 && - ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_HAIR)) { - psys->recalc &= ~PSYS_RECALC_HAIR; + ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_REDO)) { + psys->recalc &= ~PSYS_RECALC_REDO; return 1; } @@ -4717,7 +4760,7 @@ static int hair_needs_recalc(ParticleSystem *psys) } /* main particle update call, checks that things are ok on the large scale before actual particle calculations */ -void particle_system_update(Object *ob, ParticleSystem *psys) +void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd; float cfra; @@ -4725,7 +4768,7 @@ void particle_system_update(Object *ob, ParticleSystem *psys) if(!psys_check_enabled(ob, psys)) return; - cfra= bsystem_time(ob, CFRA, 0.0f); + cfra= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ @@ -4739,6 +4782,9 @@ void particle_system_update(Object *ob, ParticleSystem *psys) if(!psmd->dm) return; + if(psys->recalc & PSYS_RECALC_TYPE) + psys_changed_type(psys); + /* (re-)create hair */ if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { float hcfra=0.0f; @@ -4751,8 +4797,8 @@ void particle_system_update(Object *ob, ParticleSystem *psys) for(i=0; i<=psys->part->hair_step; i++){ hcfra=100.0f*(float)i/(float)psys->part->hair_step; - system_step(ob, psys, psmd, hcfra); - save_hair(ob, psys, psmd, hcfra); + system_step(scene, ob, psys, psmd, hcfra); + save_hair(scene, ob, psys, psmd, hcfra); } psys->flag |= PSYS_HAIR_DONE; @@ -4760,10 +4806,10 @@ void particle_system_update(Object *ob, ParticleSystem *psys) /* handle softbody hair */ if(psys->part->type==PART_HAIR && psys->soft) - psys_to_softbody(ob, psys); + psys_to_softbody(scene, ob, psys); /* the main particle system step */ - system_step(ob, psys, psmd, cfra); + system_step(scene, ob, psys, psmd, cfra); /* save matrix for duplicators */ Mat4Invert(psys->imat, ob->obmat); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index d4676653a4e..b00755f7135 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -54,7 +54,6 @@ #include "BKE_softbody.h" #include "BKE_utildefines.h" -#include "blendef.h" /* needed for directory lookup */ #ifndef WIN32 @@ -376,7 +375,7 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) return BLI_exists(filename); } -void BKE_ptcache_id_time(PTCacheID *pid, float cfra, int *startframe, int *endframe, float *timescale) +void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) { Object *ob; PointCache *cache; @@ -395,8 +394,8 @@ void BKE_ptcache_id_time(PTCacheID *pid, float cfra, int *startframe, int *endfr cache= pid->cache; if(timescale) { - time= bsystem_time(ob, cfra, 0.0f); - nexttime= bsystem_time(ob, cfra+1.0f, 0.0f); + time= bsystem_time(scene, ob, cfra, 0.0f); + nexttime= bsystem_time(scene, ob, cfra+1.0f, 0.0f); *timescale= MAX2(nexttime - time, 0.0f); } @@ -405,7 +404,8 @@ void BKE_ptcache_id_time(PTCacheID *pid, float cfra, int *startframe, int *endfr *startframe= cache->startframe; *endframe= cache->endframe; - if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) { + // XXX ipoflag is depreceated - old animation system stuff + if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) { offset= give_timeoffset(ob); *startframe += (int)(offset+0.5f); @@ -492,6 +492,8 @@ int BKE_ptcache_object_reset(Object *ob, int mode) else skip = 1; } + else if((psys->recalc & PSYS_RECALC_RESET)==0) + skip = 1; if(skip == 0) { BKE_ptcache_id_from_particles(&pid, ob, psys); @@ -553,7 +555,7 @@ void BKE_ptcache_remove(void) static int CONTINUE_PHYSICS = 0; -void BKE_ptcache_set_continue_physics(int enable) +void BKE_ptcache_set_continue_physics(Scene *scene, int enable) { Object *ob; @@ -563,7 +565,7 @@ void BKE_ptcache_set_continue_physics(int enable) if(CONTINUE_PHYSICS == 0) { for(ob=G.main->object.first; ob; ob=ob->id.next) if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_OUTDATED)) - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } } } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index d2eb058a9a0..261b58454bd 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -44,9 +44,7 @@ #include "DNA_object_types.h" #include "DNA_listBase.h" - #include "BLI_blenlib.h" -#include "BKE_bad_level_calls.h" #include "BKE_property.h" void free_property(bProperty *prop) @@ -105,19 +103,19 @@ void init_property(bProperty *prop) prop->data= 0; switch(prop->type) { - case PROP_BOOL: + case GPROP_BOOL: prop->poin= &prop->data; break; - case PROP_INT: + case GPROP_INT: prop->poin= &prop->data; break; - case PROP_FLOAT: + case GPROP_FLOAT: prop->poin= &prop->data; break; - case PROP_STRING: + case GPROP_STRING: prop->poin= MEM_callocN(MAX_PROPSTRING, "property string"); break; - case PROP_TIME: + case GPROP_TIME: prop->poin= &prop->data; break; } @@ -170,7 +168,7 @@ int compare_property(bProperty *prop, char *str) float fvalue, ftest; switch(prop->type) { - case PROP_BOOL: + case GPROP_BOOL: if(BLI_strcasecmp(str, "true")==0) { if(prop->data==1) return 0; else return 1; @@ -179,14 +177,14 @@ int compare_property(bProperty *prop, char *str) if(prop->data==0) return 0; else return 1; } - /* no break, do prop_int too! */ + /* no break, do GPROP_int too! */ - case PROP_INT: + case GPROP_INT: return prop->data - atoi(str); - case PROP_FLOAT: - case PROP_TIME: - // WARNING: untested for PROP_TIME + case GPROP_FLOAT: + case GPROP_TIME: + // WARNING: untested for GPROP_TIME // function isn't used currently fvalue= *((float *)&prop->data); ftest= (float)atof(str); @@ -194,7 +192,7 @@ int compare_property(bProperty *prop, char *str) else if( fvalue < ftest) return -1; return 0; - case PROP_STRING: + case GPROP_STRING: return strcmp(prop->poin, str); } @@ -206,19 +204,19 @@ void set_property(bProperty *prop, char *str) // extern int Gdfra; /* sector.c */ switch(prop->type) { - case PROP_BOOL: + case GPROP_BOOL: if(BLI_strcasecmp(str, "true")==0) prop->data= 1; else if(BLI_strcasecmp(str, "false")==0) prop->data= 0; else prop->data= (atoi(str)!=0); break; - case PROP_INT: + case GPROP_INT: prop->data= atoi(str); break; - case PROP_FLOAT: - case PROP_TIME: + case GPROP_FLOAT: + case GPROP_TIME: *((float *)&prop->data)= (float)atof(str); break; - case PROP_STRING: + case GPROP_STRING: strcpy(prop->poin, str); break; } @@ -230,15 +228,15 @@ void add_property(bProperty *prop, char *str) // extern int Gdfra; /* sector.c */ switch(prop->type) { - case PROP_BOOL: - case PROP_INT: + case GPROP_BOOL: + case GPROP_INT: prop->data+= atoi(str); break; - case PROP_FLOAT: - case PROP_TIME: + case GPROP_FLOAT: + case GPROP_TIME: *((float *)&prop->data)+= (float)atof(str); break; - case PROP_STRING: + case GPROP_STRING: /* strcpy(prop->poin, str); */ break; } @@ -252,15 +250,15 @@ void set_property_valstr(bProperty *prop, char *str) if(str == NULL) return; switch(prop->type) { - case PROP_BOOL: - case PROP_INT: + case GPROP_BOOL: + case GPROP_INT: sprintf(str, "%d", prop->data); break; - case PROP_FLOAT: - case PROP_TIME: + case GPROP_FLOAT: + case GPROP_TIME: sprintf(str, "%f", *((float *)&prop->data)); break; - case PROP_STRING: + case GPROP_STRING: BLI_strncpy(str, prop->poin, MAX_PROPSTRING); break; } diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c new file mode 100644 index 00000000000..116fd069948 --- /dev/null +++ b/source/blender/blenkernel/intern/report.c @@ -0,0 +1,252 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation (2008). + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "BKE_report.h" + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#ifdef _WIN32 +#ifndef vsnprintf +#define vsnprintf _vsnprintf +#endif +#endif + +static char *report_type_str(int type) +{ + switch(type) { + case RPT_DEBUG: return "Debug"; + case RPT_INFO: return "Info"; + case RPT_WARNING: return "Warning"; + case RPT_ERROR: return "Error"; + case RPT_ERROR_INVALID_INPUT: return "Invalid Input Error"; + case RPT_ERROR_INVALID_CONTEXT: return "Invalid Context Error"; + case RPT_ERROR_OUT_OF_MEMORY: return "Out Of Memory Error"; + default: return "Undefined Type"; + } +} + +void BKE_reports_init(ReportList *reports, int flag) +{ + if(!reports) + return; + + memset(reports, 0, sizeof(ReportList)); + + reports->storelevel= RPT_WARNING; + reports->printlevel= RPT_WARNING; + reports->flag= flag; +} + +void BKE_reports_clear(ReportList *reports) +{ + Report *report; + + if(!reports) + return; + + for(report=reports->list.first; report; report=report->next) + MEM_freeN(report->message); + + BLI_freelistN(&reports->list); +} + +void BKE_report(ReportList *reports, ReportType type, const char *message) +{ + Report *report; + int len; + + if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { + printf("%s: %s\n", report_type_str(type), message); + fflush(stdout); /* this ensures the message is printed before a crash */ + } + + if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) { + report= MEM_callocN(sizeof(Report), "Report"); + report->type= type; + report->typestr= report_type_str(type); + + len= strlen(message); + report->message= MEM_callocN(sizeof(char)*(len+1), "ReportMessage"); + memcpy(report->message, message, sizeof(char)*(len+1)); + + BLI_addtail(&reports->list, report); + } +} + +void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) +{ + DynStr *ds; + Report *report; + va_list args; + + if(!reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) { + va_start(args, format); + vprintf(format, args); + va_end(args); + fflush(stdout); /* this ensures the message is printed before a crash */ + } + + if(reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) { + report= MEM_callocN(sizeof(Report), "Report"); + + ds= BLI_dynstr_new(); + va_start(args, format); + BLI_dynstr_vappendf(ds, format, args); + va_end(args); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + + report->type= type; + report->typestr= report_type_str(type); + + BLI_addtail(&reports->list, report); + } +} + +void BKE_reports_prepend(ReportList *reports, const char *prepend) +{ + Report *report; + DynStr *ds; + + if(!reports) + return; + + for(report=reports->list.first; report; report=report->next) { + ds= BLI_dynstr_new(); + + BLI_dynstr_append(ds, prepend); + BLI_dynstr_append(ds, report->message); + MEM_freeN(report->message); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + } +} + +void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) +{ + Report *report; + DynStr *ds; + va_list args; + + if(!reports) + return; + + for(report=reports->list.first; report; report=report->next) { + ds= BLI_dynstr_new(); + va_start(args, prepend); + BLI_dynstr_vappendf(ds, prepend, args); + va_end(args); + + BLI_dynstr_append(ds, report->message); + MEM_freeN(report->message); + + report->message= BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + } +} + +ReportType BKE_report_print_level(ReportList *reports) +{ + if(!reports) + return RPT_ERROR; + + return reports->printlevel; +} + +void BKE_report_print_level_set(ReportList *reports, ReportType level) +{ + if(!reports) + return; + + reports->printlevel= level; +} + +ReportType BKE_report_store_level(ReportList *reports) +{ + if(!reports) + return RPT_ERROR; + + return reports->storelevel; +} + +void BKE_report_store_level_set(ReportList *reports, ReportType level) +{ + if(!reports) + return; + + reports->storelevel= level; +} + +char *BKE_reports_string(ReportList *reports, ReportType level) +{ + Report *report; + DynStr *ds; + char *cstring; + + if(!reports) + return NULL; + + ds= BLI_dynstr_new(); + for(report=reports->list.first; report; report=report->next) + if(report->type >= level) + BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message); + + if (BLI_dynstr_get_len(ds)) + cstring= BLI_dynstr_get_cstring(ds); + else + cstring= NULL; + + BLI_dynstr_free(ds); + return cstring; +} + +void BKE_reports_print(ReportList *reports, ReportType level) +{ + char *cstring = BKE_reports_string(reports, level); + + if (cstring == NULL) + return; + + printf("%s", cstring); + fflush(stdout); + MEM_freeN(cstring); +} + diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 47d11bb9d29..74d2347ec39 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -37,7 +37,6 @@ #include <string.h> #include "MEM_guardedalloc.h" -#include "nla.h" /* For __NLA: Important, do not remove */ #include "DNA_text_types.h" #include "DNA_controller_types.h" #include "DNA_sensor_types.h" @@ -45,13 +44,14 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_blender.h" #include "BKE_sca.h" +//#include "wm_event_types.h" + void free_text_controllers(Text *txt) { Object *ob; @@ -134,7 +134,7 @@ void init_sensor(bSensor *sens) switch(sens->type) { case SENS_ALWAYS: - sens->pulse = 1; + sens->pulse = 0; break; case SENS_TOUCH: sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens"); @@ -158,7 +158,7 @@ void init_sensor(bSensor *sens) break; case SENS_MOUSE: ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens"); - ms->type= LEFTMOUSE; + //XXX ms->type= LEFTMOUSE; break; case SENS_COLLISION: sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens"); @@ -195,7 +195,7 @@ bSensor *new_sensor(int type) init_sensor(sens); strcpy(sens->name, "sensor"); - make_unique_prop_names(sens->name); +// XXX make_unique_prop_names(sens->name); return sens; } @@ -319,7 +319,7 @@ bController *new_controller(int type) init_controller(cont); strcpy(cont->name, "cont"); - make_unique_prop_names(cont->name); +// XXX make_unique_prop_names(cont->name); return cont; } @@ -491,7 +491,7 @@ bActuator *new_actuator(int type) init_actuator(act); strcpy(act->name, "act"); - make_unique_prop_names(act->name); +// XXX make_unique_prop_names(act->name); return act; } @@ -579,6 +579,10 @@ void set_sca_new_poins_ob(Object *ob) bCameraActuator *ca= act->data; ID_NEW(ca->ob); } + else if(act->type==ACT_OBJECT) { + bObjectActuator *oa= act->data; + ID_NEW(oa->reference); + } else if(act->type==ACT_SCENE) { bSceneActuator *sca= act->data; ID_NEW(sca->camera); @@ -606,6 +610,7 @@ void sca_remove_ob_poin(Object *obt, Object *ob) bMessageSensor *ms; bActuator *act; bCameraActuator *ca; + bObjectActuator *oa; bSceneActuator *sa; bEditObjectActuator *eoa; bPropertyActuator *pa; @@ -628,6 +633,10 @@ void sca_remove_ob_poin(Object *obt, Object *ob) ca= act->data; if(ca->ob==ob) ca->ob= NULL; break; + case ACT_OBJECT: + oa= act->data; + if(oa->reference==ob) oa->reference= NULL; + break; case ACT_PROPERTY: pa= act->data; if(pa->ob==ob) pa->ob= NULL; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5def3577218..156bdae9b00 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -43,6 +43,7 @@ #endif #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_color_types.h" #include "DNA_constraint_types.h" @@ -59,8 +60,9 @@ #include "BKE_action.h" #include "BKE_anim.h" +#include "BKE_animsys.h" #include "BKE_armature.h" -#include "BKE_bad_level_calls.h" +#include "BKE_colortools.h" #include "BKE_colortools.h" #include "BKE_constraint.h" #include "BKE_depsgraph.h" @@ -76,11 +78,12 @@ #include "BKE_object.h" #include "BKE_scene.h" #include "BKE_sculpt.h" +#include "BKE_sequence.h" #include "BKE_world.h" #include "BKE_utildefines.h" -#include "BIF_previewrender.h" -#include "BIF_editseq.h" +//XXX #include "BIF_previewrender.h" +//XXX #include "BIF_editseq.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" @@ -89,7 +92,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "nla.h" +//XXX #include "nla.h" #ifdef WIN32 #else @@ -138,13 +141,16 @@ void free_scene(Scene *sce) /* do not free objects! */ BLI_freelistN(&sce->base); - free_editing(sce->ed); + seq_free_editing(sce->ed); if(sce->radio) MEM_freeN(sce->radio); sce->radio= 0; #ifndef DISABLE_PYTHON BPY_free_scriptlink(&sce->scriptlink); #endif + + BKE_free_animdata((ID *)sce); + BKE_keyingsets_free(&sce->keyingsets); if (sce->r.avicodecdata) { free_avicodecdata(sce->r.avicodecdata); @@ -166,7 +172,16 @@ void free_scene(Scene *sce) BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); - if(sce->toolsettings){ + if(sce->toolsettings) { + if(sce->toolsettings->vpaint) + MEM_freeN(sce->toolsettings->vpaint); + if(sce->toolsettings->wpaint) + MEM_freeN(sce->toolsettings->wpaint); + if(sce->toolsettings->sculpt) { + sculptsession_free(sce->toolsettings->sculpt); + MEM_freeN(sce->toolsettings->sculpt); + } + MEM_freeN(sce->toolsettings); sce->toolsettings = NULL; } @@ -180,8 +195,6 @@ void free_scene(Scene *sce) ntreeFreeTree(sce->nodetree); MEM_freeN(sce->nodetree); } - - sculptdata_free(sce); } Scene *add_scene(char *name) @@ -232,9 +245,9 @@ Scene *add_scene(char *name) sce->r.stereomode = 1; // no stereo sce->r.domeangle = 180; sce->r.domemode = 1; - sce->r.domesize = 1.0f; sce->r.domeres = 4; sce->r.domeresbuf = 1.0f; + sce->r.dometilt = 0; sce->r.simplify_subsurf= 6; sce->r.simplify_particles= 1.0f; @@ -279,6 +292,8 @@ Scene *add_scene(char *name) sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; + sce->toolsettings->proportional_size = 1.0f; + pset= &sce->toolsettings->particle; pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER; pset->emitterdist= 0.25f; @@ -301,8 +316,6 @@ Scene *add_scene(char *name) BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f); sce->r.osa= 8; - sculptdata_init(sce); - /* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */ scene_add_render_layer(sce); @@ -321,21 +334,17 @@ Base *object_in_scene(Object *ob, Scene *sce) return NULL; } -void set_scene_bg(Scene *sce) +void set_scene_bg(Scene *scene) { + Scene *sce; Base *base; Object *ob; Group *group; GroupObject *go; int flag; - // Note: this here is defined in editseq.c (BIF_editseq.h), NOT in blenkernel! - clear_last_seq(); - - G.scene= sce; - /* check for cyclic sets, for reading old files but also for definite security (py?) */ - scene_check_setscene(G.scene); + scene_check_setscene(scene); /* deselect objects (for dataselect) */ for(ob= G.main->object.first; ob; ob= ob->id.next) @@ -351,15 +360,15 @@ void set_scene_bg(Scene *sce) } /* sort baselist */ - DAG_scene_sort(sce); + DAG_scene_sort(scene); /* ensure dags are built for sets */ - for(sce= sce->set; sce; sce= sce->set) + for(sce= scene->set; sce; sce= sce->set) if(sce->theDag==NULL) DAG_scene_sort(sce); /* copy layers and flags from bases to objects */ - for(base= G.scene->base.first; base; base= base->next) { + for(base= scene->base.first; base; base= base->next) { ob= base->object; ob->lay= base->lay; @@ -392,41 +401,50 @@ void set_scene_name(char *name) } } - error("Can't find scene: %s", name); + //XXX error("Can't find scene: %s", name); } /* used by metaballs * doesnt return the original duplicated object, only dupli's */ -int next_object(int val, Base **base, Object **ob) +int next_object(Scene *scene, int val, Base **base, Object **ob) { static ListBase *duplilist= NULL; static DupliObject *dupob; - static int fase; + static int fase= F_START, in_next_object= 0; int run_again=1; /* init */ if(val==0) { fase= F_START; dupob= NULL; + + /* XXX particle systems with metas+dupligroups call this recursively */ + /* see bug #18725 */ + if(in_next_object) { + printf("ERROR: MetaBall generation called recursively, not supported\n"); + + return F_ERROR; + } } else { - + in_next_object= 1; + /* run_again is set when a duplilist has been ended */ while(run_again) { run_again= 0; /* the first base */ if(fase==F_START) { - *base= G.scene->base.first; + *base= scene->base.first; if(*base) { *ob= (*base)->object; fase= F_SCENE; } else { /* exception: empty scene */ - if(G.scene->set && G.scene->set->base.first) { - *base= G.scene->set->base.first; + if(scene->set && scene->set->base.first) { + *base= scene->set->base.first; *ob= (*base)->object; fase= F_SET; } @@ -439,8 +457,8 @@ int next_object(int val, Base **base, Object **ob) else { if(fase==F_SCENE) { /* scene is finished, now do the set */ - if(G.scene->set && G.scene->set->base.first) { - *base= G.scene->set->base.first; + if(scene->set && scene->set->base.first) { + *base= scene->set->base.first; *ob= (*base)->object; fase= F_SET; } @@ -457,7 +475,7 @@ int next_object(int val, Base **base, Object **ob) this enters eternal loop because of makeDispListMBall getting called inside of group_duplilist */ if((*base)->object->dup_group == NULL) { - duplilist= object_duplilist(G.scene, (*base)->object); + duplilist= object_duplilist(scene, (*base)->object); dupob= duplilist->first; @@ -493,6 +511,9 @@ int next_object(int val, Base **base, Object **ob) } } + /* reset recursion test */ + in_next_object= 0; + return fase; } @@ -564,38 +585,66 @@ int scene_check_setscene(Scene *sce) return 1; } +/* This (evil) function is needed to cope with two legacy Blender rendering features +* mblur (motion blur that renders 'subframes' and blurs them together), and fields +* rendering. Thus, the use of ugly globals from object.c +*/ +// BAD... EVIL... JUJU...!!!! +// XXX moved here temporarily +float frame_to_float (Scene *scene, int cfra) /* see also bsystem_time in object.c */ +{ + extern float bluroffs; /* bad stuff borrowed from object.c */ + extern float fieldoffs; + float ctime; + + ctime= (float)cfra; + ctime+= bluroffs+fieldoffs; + ctime*= scene->r.framelen; + + return ctime; +} + static void scene_update(Scene *sce, unsigned int lay) { Base *base; Object *ob; + float ctime = frame_to_float(sce, sce->r.cfra); if(sce->theDag==NULL) DAG_scene_sort(sce); DAG_scene_update_flags(sce, lay); // only stuff that moves or needs display still + /* All 'standard' (i.e. without any dependencies) animation is handled here, + * with an 'local' to 'macro' order of evaluation. This should ensure that + * settings stored nestled within a hierarchy (i.e. settings in a Texture block + * can be overridden by settings from Scene, which owns the Texture through a hierarchy + * such as Scene->World->MTex/Texture) can still get correctly overridden. + */ + BKE_animsys_evaluate_all_animation(G.main, ctime); + for(base= sce->base.first; base; base= base->next) { ob= base->object; - object_handle_update(ob); // bke_object.h + object_handle_update(sce, ob); // bke_object.h /* only update layer when an ipo */ - if(ob->ipo && has_ipo_code(ob->ipo, OB_LAY) ) { - base->lay= ob->lay; - } + // XXX old animation system + //if(ob->ipo && has_ipo_code(ob->ipo, OB_LAY) ) { + // base->lay= ob->lay; + //} } } + /* applies changes right away, does all sets too */ void scene_update_for_newframe(Scene *sce, unsigned int lay) { Scene *scene= sce; - /* clears all BONE_UNKEYED flags for every pose's pchans */ - framechange_poses_clear_unkeyed(); + /* clear animation overrides */ + // XXX TODO... - /* object ipos are calculated in where_is_object */ - do_all_data_ipos(); #ifndef DISABLE_PYTHON if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED, 0); #endif @@ -622,130 +671,26 @@ void scene_add_render_layer(Scene *sce) srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z; } -/* Initialize 'permanent' sculpt data that is saved with file kept after - switching out of sculptmode. */ -void sculptdata_init(Scene *sce) +void sculptsession_free(Sculpt *sculpt) { - SculptData *sd; - - if(!sce) - return; - - sd= &sce->sculptdata; - - if(sd->cumap) { - curvemapping_free(sd->cumap); - sd->cumap = NULL; - } - - memset(sd, 0, sizeof(SculptData)); - - sd->drawbrush.size = sd->smoothbrush.size = sd->pinchbrush.size = - sd->inflatebrush.size = sd->grabbrush.size = - sd->layerbrush.size = sd->flattenbrush.size = 50; - sd->drawbrush.strength = sd->smoothbrush.strength = - sd->pinchbrush.strength = sd->inflatebrush.strength = - sd->grabbrush.strength = sd->layerbrush.strength = - sd->flattenbrush.strength = 25; - sd->drawbrush.dir = sd->pinchbrush.dir = sd->inflatebrush.dir = sd->layerbrush.dir= 1; - sd->drawbrush.flag = sd->smoothbrush.flag = - sd->pinchbrush.flag = sd->inflatebrush.flag = - sd->layerbrush.flag = sd->flattenbrush.flag = 0; - sd->drawbrush.view= 0; - sd->brush_type= DRAW_BRUSH; - sd->texact= -1; - sd->texfade= 1; - sd->averaging= 1; - sd->texsep= 0; - sd->texrept= SCULPTREPT_DRAG; - sd->flags= SCULPT_DRAW_BRUSH; - sd->tablet_size=3; - sd->tablet_strength=10; - sd->rake=0; - sculpt_reset_curve(sd); -} - -void sculptdata_free(Scene *sce) -{ - SculptData *sd= &sce->sculptdata; - int a; - - sculptsession_free(sce); - - for(a=0; a<MAX_MTEX; a++) { - MTex *mtex= sd->mtex[a]; - if(mtex) { - if(mtex->tex) mtex->tex->id.us--; - MEM_freeN(mtex); - } - } - - curvemapping_free(sd->cumap); - sd->cumap = NULL; -} - -void sculpt_vertexusers_free(SculptSession *ss) -{ - if(ss && ss->vertex_users){ - MEM_freeN(ss->vertex_users); - MEM_freeN(ss->vertex_users_mem); - ss->vertex_users= NULL; - ss->vertex_users_mem= NULL; - ss->vertex_users_size= 0; - } -} - -void sculptsession_free(Scene *sce) -{ - SculptSession *ss= sce->sculptdata.session; + SculptSession *ss= sculpt->session; if(ss) { if(ss->projverts) MEM_freeN(ss->projverts); - if(ss->mats) - MEM_freeN(ss->mats); - if(ss->radialcontrol) - MEM_freeN(ss->radialcontrol); + if(ss->fmap) + MEM_freeN(ss->fmap); + + if(ss->fmap_mem) + MEM_freeN(ss->fmap_mem); - sculpt_vertexusers_free(ss); if(ss->texcache) MEM_freeN(ss->texcache); MEM_freeN(ss); - sce->sculptdata.session= NULL; + sculpt->session= NULL; } } -/* Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1 */ -void sculpt_reset_curve(SculptData *sd) -{ - CurveMap *cm = NULL; - - if(!sd->cumap) - sd->cumap = curvemapping_add(1, 0, 0, 1, 1); - - cm = sd->cumap->cm; - - if(cm->curve) - MEM_freeN(cm->curve); - cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points"); - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - cm->totpoint= 6; - cm->curve[0].x= 0; - cm->curve[0].y= 1; - cm->curve[1].x= 0.1; - cm->curve[1].y= 0.97553; - cm->curve[2].x= 0.3; - cm->curve[2].y= 0.79389; - cm->curve[3].x= 0.9; - cm->curve[3].y= 0.02447; - cm->curve[4].x= 0.7; - cm->curve[4].y= 0.20611; - cm->curve[5].x= 1; - cm->curve[5].y= 0; - - curvemapping_changed(sd->cumap, 0); -} - /* render simplification */ int get_render_subsurf_level(RenderData *r, int lvl) @@ -790,4 +735,4 @@ void free_dome_warp_text(struct Text *txt) scene->r.dometext = NULL; scene = scene->id.next; } -}
\ No newline at end of file +} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 7a45493e1f4..e25e4be90c8 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -1,6 +1,4 @@ - -/* screen.c - * +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -33,22 +31,289 @@ #include <stdio.h> #include <math.h> +#include "MEM_guardedalloc.h" + #include "DNA_screen_types.h" -#include "BKE_bad_level_calls.h" +#include "DNA_space_types.h" + #include "BLI_blenlib.h" #include "BKE_screen.h" -#ifdef HAVE_CONFIG_H -#include <config.h> +#ifndef DISABLE_PYTHON +#include "BPY_extern.h" +#endif + +/* ************ Spacetype/regiontype handling ************** */ + +/* keep global; this has to be accessible outside of windowmanager */ +static ListBase spacetypes= {NULL, NULL}; + +/* not SpaceType itself */ +static void spacetype_free(SpaceType *st) +{ + ARegionType *art; + PanelType *pt; + HeaderType *ht; + MenuType *mt; + + for(art= st->regiontypes.first; art; art= art->next) { + BLI_freelistN(&art->drawcalls); + + for(pt= art->paneltypes.first; pt; pt= pt->next) + if(pt->py_free) + pt->py_free(pt->py_data); + + for(ht= art->headertypes.first; ht; ht= ht->next) + if(ht->py_free) + ht->py_free(ht->py_data); + + for(mt= art->menutypes.first; mt; mt= mt->next) + if(mt->py_free) + mt->py_free(mt->py_data); + + BLI_freelistN(&art->paneltypes); + BLI_freelistN(&art->headertypes); + BLI_freelistN(&art->menutypes); + } + + BLI_freelistN(&st->regiontypes); +} + +void BKE_spacetypes_free(void) +{ + SpaceType *st; + + for(st= spacetypes.first; st; st= st->next) { + spacetype_free(st); + } + + BLI_freelistN(&spacetypes); +} + +SpaceType *BKE_spacetype_from_id(int spaceid) +{ + SpaceType *st; + + for(st= spacetypes.first; st; st= st->next) { + if(st->spaceid==spaceid) + return st; + } + return NULL; +} + +ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid) +{ + ARegionType *art; + + for(art= st->regiontypes.first; art; art= art->next) + if(art->regionid==regionid) + return art; + + printf("Error, region type missing in %s\n", st->name); + return st->regiontypes.first; +} + + +const ListBase *BKE_spacetypes_list() +{ + return &spacetypes; +} + +void BKE_spacetype_register(SpaceType *st) +{ + SpaceType *stype; + + /* sanity check */ + stype= BKE_spacetype_from_id(st->spaceid); + if(stype) { + printf("error: redefinition of spacetype %s\n", stype->name); + spacetype_free(stype); + MEM_freeN(stype); + } + + BLI_addtail(&spacetypes, st); +} + +/* ***************** Space handling ********************** */ + +void BKE_spacedata_freelist(ListBase *lb) +{ + SpaceLink *sl; + ARegion *ar; + + for (sl= lb->first; sl; sl= sl->next) { + SpaceType *st= BKE_spacetype_from_id(sl->spacetype); + + /* free regions for pushed spaces */ + for(ar=sl->regionbase.first; ar; ar=ar->next) + BKE_area_region_free(st, ar); + + BLI_freelistN(&sl->regionbase); + + if(st && st->free) + st->free(sl); + } + + BLI_freelistN(lb); +} + +ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) +{ + ARegion *newar= MEM_dupallocN(ar); + Panel *pa, *newpa, *patab; + + newar->prev= newar->next= NULL; + newar->handlers.first= newar->handlers.last= NULL; + newar->uiblocks.first= newar->uiblocks.last= NULL; + newar->swinid= 0; + + /* use optional regiondata callback */ + if(ar->regiondata) { + ARegionType *art= BKE_regiontype_from_id(st, ar->regiontype); + + if(art && art->duplicate) + newar->regiondata= art->duplicate(ar->regiondata); + else + newar->regiondata= MEM_dupallocN(ar->regiondata); + } + + newar->panels.first= newar->panels.last= NULL; + BLI_duplicatelist(&newar->panels, &ar->panels); + + /* copy panel pointers */ + for(newpa= newar->panels.first; newpa; newpa= newpa->next) { + patab= newar->panels.first; + pa= ar->panels.first; + while(patab) { + if(newpa->paneltab == pa) { + newpa->paneltab = patab; + break; + } + patab= patab->next; + pa= pa->next; + } + } + + return newar; +} + + +/* from lb2 to lb1, lb1 is supposed to be free'd */ +static void region_copylist(SpaceType *st, ListBase *lb1, ListBase *lb2) +{ + ARegion *ar; + + /* to be sure */ + lb1->first= lb1->last= NULL; + + for(ar= lb2->first; ar; ar= ar->next) { + ARegion *arnew= BKE_area_region_copy(st, ar); + BLI_addtail(lb1, arnew); + } +} + + +/* lb1 should be empty */ +void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2) +{ + SpaceLink *sl; + + lb1->first= lb1->last= NULL; /* to be sure */ + + for (sl= lb2->first; sl; sl= sl->next) { + SpaceType *st= BKE_spacetype_from_id(sl->spacetype); + + if(st && st->duplicate) { + SpaceLink *slnew= st->duplicate(sl); + + BLI_addtail(lb1, slnew); + + region_copylist(st, &slnew->regionbase, &sl->regionbase); + } + } +} + +/* lb1 should be empty */ +void BKE_spacedata_copyfirst(ListBase *lb1, ListBase *lb2) +{ + SpaceLink *sl; + + lb1->first= lb1->last= NULL; /* to be sure */ + + sl= lb2->first; + if(sl) { + SpaceType *st= BKE_spacetype_from_id(sl->spacetype); + + if(st && st->duplicate) { + SpaceLink *slnew= st->duplicate(sl); + + BLI_addtail(lb1, slnew); + + region_copylist(st, &slnew->regionbase, &sl->regionbase); + } + } +} + +/* not region itself */ +void BKE_area_region_free(SpaceType *st, ARegion *ar) +{ + if(st) { + ARegionType *art= BKE_regiontype_from_id(st, ar->regiontype); + + if(art && art->free) + art->free(ar); + + if(ar->regiondata) + printf("regiondata free error\n"); + } + else if(ar->type && ar->type->free) + ar->type->free(ar); + + if(ar) { + BLI_freelistN(&ar->panels); + } +} + +/* not area itself */ +void BKE_screen_area_free(ScrArea *sa) +{ + SpaceType *st= BKE_spacetype_from_id(sa->spacetype); + ARegion *ar; + + for(ar=sa->regionbase.first; ar; ar=ar->next) + BKE_area_region_free(st, ar); + + BLI_freelistN(&sa->regionbase); + + BKE_spacedata_freelist(&sa->spacedata); + + BLI_freelistN(&sa->actionzones); + +#ifndef DISABLE_PYTHON + BPY_free_scriptlink(&sa->scriptlink); #endif +} /* don't free screen itself */ void free_screen(bScreen *sc) { - unlink_screen(sc); + ScrArea *sa, *san; + ARegion *ar; + + for(ar=sc->regionbase.first; ar; ar=ar->next) + BKE_area_region_free(NULL, ar); + BLI_freelistN(&sc->regionbase); + + for(sa= sc->areabase.first; sa; sa= san) { + san= sa->next; + BKE_screen_area_free(sa); + } + BLI_freelistN(&sc->vertbase); BLI_freelistN(&sc->edgebase); BLI_freelistN(&sc->areabase); } + + diff --git a/source/blender/blenkernel/intern/script.c b/source/blender/blenkernel/intern/script.c index 6145f6c3063..e34b1d0a1dd 100644 --- a/source/blender/blenkernel/intern/script.c +++ b/source/blender/blenkernel/intern/script.c @@ -35,7 +35,6 @@ #include "DNA_space_types.h" #include "MEM_guardedalloc.h" -#include "BKE_bad_level_calls.h" /* for BPY_clear_script */ /* #include "BLI_blenlib.h" @@ -47,15 +46,14 @@ #ifndef DISABLE_PYTHON #include "BPY_extern.h" // Blender Python library #endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif */ /* XXX this function and so also the file should not be needed anymore, * since we have to force clearing all Python related data before freeing * Blender's library. Still testing, will decide later (Willian). */ + +//XXX +#if 0 void free_script (Script *script) { if (!script) return; @@ -63,3 +61,4 @@ void free_script (Script *script) BPY_clear_script(script); #endif } +#endif diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c new file mode 100644 index 00000000000..2ee95ed928e --- /dev/null +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -0,0 +1,3155 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * - Blender Foundation, 2003-2009 + * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <string.h> +#include <math.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" +#include "PIL_dynlib.h" + +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_global.h" +#include "BKE_plugin_types.h" +#include "BKE_sequence.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +/* **** XXX **** */ +static void error() {} + +#define INT 96 +#define FLO 128 + +/* **** XXX **** */ + +/* Glow effect */ +enum { + GlowR=0, + GlowG=1, + GlowB=2, + GlowA=3 +}; + + +/* ********************************************************************** + PLUGINS + ********************************************************************** */ + +static void open_plugin_seq(PluginSeq *pis, const char *seqname) +{ + int (*version)(); + void* (*alloc_private)(); + char *cp; + + /* to be sure: (is tested for) */ + pis->doit= 0; + pis->pname= 0; + pis->varstr= 0; + pis->cfra= 0; + pis->version= 0; + pis->instance_private_data = 0; + + /* clear the error list */ + PIL_dynlib_get_error_as_string(NULL); + + /* if(pis->handle) PIL_dynlib_close(pis->handle); */ + /* pis->handle= 0; */ + + /* open the needed object */ + pis->handle= PIL_dynlib_open(pis->name); + if(test_dlerr(pis->name, pis->name)) return; + + if (pis->handle != 0) { + /* find the address of the version function */ + version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); + if (test_dlerr(pis->name, "plugin_seq_getversion")) return; + + if (version != 0) { + pis->version= version(); + if (pis->version >= 2 && pis->version <= 6) { + int (*info_func)(PluginInfo *); + PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info"); + + info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo"); + + if(info_func == NULL) error("No info func"); + else { + info_func(info); + + pis->pname= info->name; + pis->vars= info->nvars; + pis->cfra= info->cfra; + + pis->varstr= info->varstr; + + pis->doit= (void(*)(void))info->seq_doit; + if (info->init) + info->init(); + } + MEM_freeN(info); + + cp= PIL_dynlib_find_symbol(pis->handle, "seqname"); + if(cp) strncpy(cp, seqname, 21); + } else { + printf ("Plugin returned unrecognized version number\n"); + return; + } + } + alloc_private = (void* (*)())PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_alloc_private_data"); + if (alloc_private) { + pis->instance_private_data = alloc_private(); + } + + pis->current_private_data = (void**) + PIL_dynlib_find_symbol( + pis->handle, "plugin_private_data"); + } +} + +static PluginSeq *add_plugin_seq(const char *str, const char *seqname) +{ + PluginSeq *pis; + VarStruct *varstr; + int a; + + pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq"); + + strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE); + open_plugin_seq(pis, seqname); + + if(pis->doit==0) { + if(pis->handle==0) error("no plugin: %s", str); + else error("in plugin: %s", str); + MEM_freeN(pis); + return 0; + } + + /* default values */ + varstr= pis->varstr; + for(a=0; a<pis->vars; a++, varstr++) { + if( (varstr->type & FLO)==FLO) + pis->data[a]= varstr->def; + else if( (varstr->type & INT)==INT) + *((int *)(pis->data+a))= (int) varstr->def; + } + + return pis; +} + +static void free_plugin_seq(PluginSeq *pis) +{ + if(pis==0) return; + + /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ + + if (pis->instance_private_data) { + void (*free_private)(void *); + + free_private = (void (*)(void *))PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_free_private_data"); + if (free_private) { + free_private(pis->instance_private_data); + } + } + + MEM_freeN(pis); +} + +static void init_plugin(Sequence * seq, const char * fname) +{ + seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2); +} + +/* + * FIXME: should query plugin! Could be generator, that needs zero inputs... + */ +static int num_inputs_plugin() +{ + return 1; +} + +static void load_plugin(Sequence * seq) +{ + if (seq) { + open_plugin_seq(seq->plugin, seq->name+2); + } +} + +static void copy_plugin(Sequence * dst, Sequence * src) +{ + if(src->plugin) { + dst->plugin= MEM_dupallocN(src->plugin); + open_plugin_seq(dst->plugin, dst->name+2); + } +} + +static ImBuf * IMB_cast_away_list(ImBuf * i) +{ + if (!i) { + return 0; + } + return (ImBuf*) (((void**) i) + 2); +} + +static void do_plugin_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + char *cp; + int float_rendering; + int use_temp_bufs = 0; /* Are needed since blur.c (and maybe some other + old plugins) do very bad stuff + with imbuf-internals */ + + if(seq->plugin && seq->plugin->doit) { + + if(seq->plugin->cfra) + *(seq->plugin->cfra)= cfra; +// XXX *(seq->plugin->cfra)= frame_to_float(scene, cfra); + + cp = PIL_dynlib_find_symbol( + seq->plugin->handle, "seqname"); + + if(cp) strncpy(cp, seq->name+2, 22); + + if (seq->plugin->current_private_data) { + *seq->plugin->current_private_data + = seq->plugin->instance_private_data; + } + + float_rendering = (out->rect_float != NULL); + + if (seq->plugin->version<=3 && float_rendering) { + use_temp_bufs = 1; + + if (ibuf1) { + ibuf1 = IMB_dupImBuf(ibuf1); + IMB_rect_from_float(ibuf1); + imb_freerectfloatImBuf(ibuf1); + ibuf1->flags &= ~IB_rectfloat; + } + if (ibuf2) { + ibuf2 = IMB_dupImBuf(ibuf2); + IMB_rect_from_float(ibuf2); + imb_freerectfloatImBuf(ibuf2); + ibuf2->flags &= ~IB_rectfloat; + } + if (ibuf3) { + ibuf3 = IMB_dupImBuf(ibuf3); + IMB_rect_from_float(ibuf3); + imb_freerectfloatImBuf(ibuf3); + ibuf3->flags &= ~IB_rectfloat; + } + if (!out->rect) imb_addrectImBuf(out); + imb_freerectfloatImBuf(out); + out->flags &= ~IB_rectfloat; + } + + if (seq->plugin->version<=2) { + if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1); + if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2); + if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3); + } + + if (seq->plugin->version<=4) { + ((SeqDoit)seq->plugin->doit)( + seq->plugin->data, facf0, facf1, x, y, + IMB_cast_away_list(ibuf1), + IMB_cast_away_list(ibuf2), + IMB_cast_away_list(out), + IMB_cast_away_list(ibuf3)); + } else { + ((SeqDoit)seq->plugin->doit)( + seq->plugin->data, facf0, facf1, x, y, + ibuf1, ibuf2, out, ibuf3); + } + + if (seq->plugin->version<=2) { + if (!use_temp_bufs) { + if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1); + if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2); + if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3); + } + IMB_convert_rgba_to_abgr(out); + } + if (seq->plugin->version<=3 && float_rendering) { + IMB_float_from_rect(out); + } + + if (use_temp_bufs) { + if (ibuf1) IMB_freeImBuf(ibuf1); + if (ibuf2) IMB_freeImBuf(ibuf2); + if (ibuf3) IMB_freeImBuf(ibuf3); + } + } +} + +static int do_plugin_early_out(struct Sequence *seq, + float facf0, float facf1) +{ + return 0; +} + +static void free_plugin(struct Sequence * seq) +{ + free_plugin_seq(seq->plugin); + seq->plugin = 0; +} + +/* ********************************************************************** + ALPHA OVER + ********************************************************************** */ + +static void init_alpha_over_or_under(Sequence * seq) +{ + Sequence * seq1 = seq->seq1; + Sequence * seq2 = seq->seq2; + + seq->seq2= seq1; + seq->seq1= seq2; +} + +static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, + char * rect1, char *rect2, char *out) +{ + int fac2, mfac, fac, fac4; + int xo, tempc; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac2= (int)(256.0*facf0); + fac4= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 over rt2 (alpha from rt1) */ + + fac= fac2; + mfac= 256 - ( (fac2*rt1[3])>>8 ); + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else { + tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; + if(tempc>255) rt[0]= 255; else rt[0]= tempc; + tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; + if(tempc>255) rt[1]= 255; else rt[1]= tempc; + tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; + if(tempc>255) rt[2]= 255; else rt[2]= tempc; + tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; + if(tempc>255) rt[3]= 255; else rt[3]= tempc; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + fac= fac4; + mfac= 256 - ( (fac4*rt1[3])>>8 ); + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else { + tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; + if(tempc>255) rt[0]= 255; else rt[0]= tempc; + tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; + if(tempc>255) rt[1]= 255; else rt[1]= tempc; + tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; + if(tempc>255) rt[2]= 255; else rt[2]= tempc; + tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; + if(tempc>255) rt[3]= 255; else rt[3]= tempc; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, + float * rect1, float *rect2, float *out) +{ + float fac2, mfac, fac, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac4= facf1; + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 over rt2 (alpha from rt1) */ + + fac= fac2; + mfac= 1.0 - (fac2*rt1[3]) ; + + if(fac <= 0.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else if(mfac <=0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else { + rt[0] = fac*rt1[0] + mfac*rt2[0]; + rt[1] = fac*rt1[1] + mfac*rt2[1]; + rt[2] = fac*rt1[2] + mfac*rt2[2]; + rt[3] = fac*rt1[3] + mfac*rt2[3]; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + fac= fac4; + mfac= 1.0 - (fac4*rt1[3]); + + if(fac <= 0.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else if(mfac <= 0.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else { + rt[0] = fac*rt1[0] + mfac*rt2[0]; + rt[1] = fac*rt1[1] + mfac*rt2[1]; + rt[2] = fac*rt1[2] + mfac*rt2[2]; + rt[3] = fac*rt1[3] + mfac*rt2[3]; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaover_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_alphaover_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_alphaover_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + ALPHA UNDER + ********************************************************************** */ + +void do_alphaunder_effect_byte( + float facf0, float facf1, int x, int y, char *rect1, + char *rect2, char *out) +{ + int fac2, mfac, fac, fac4; + int xo; + char *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= (int)(256.0*facf0); + fac4= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 under rt2 (alpha from rt2) */ + + /* this complex optimalisation is because the + * 'skybuf' can be crossed in + */ + if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + mfac= rt2[3]; + fac= (fac2*(256-mfac))>>8; + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; + rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; + rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; + rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + mfac= rt2[3]; + fac= (fac4*(256-mfac))>>8; + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; + rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; + rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; + rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + + +static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + float fac2, mfac, fac, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac4= facf1; + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 under rt2 (alpha from rt2) */ + + /* this complex optimalisation is because the + * 'skybuf' can be crossed in + */ + if( rt2[3]<=0 && fac2>=1.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else if(rt2[3]>=1.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + mfac = rt2[3]; + fac = fac2 * (1.0 - mfac); + + if(fac == 0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + rt[0]= fac*rt1[0] + mfac*rt2[0]; + rt[1]= fac*rt1[1] + mfac*rt2[1]; + rt[2]= fac*rt1[2] + mfac*rt2[2]; + rt[3]= fac*rt1[3] + mfac*rt2[3]; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + if(rt2[3]<=0 && fac4 >= 1.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + + } else if(rt2[3]>=1.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + mfac= rt2[3]; + fac= fac4*(1.0-mfac); + + if(fac == 0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + rt[0]= fac * rt1[0] + mfac * rt2[0]; + rt[1]= fac * rt1[1] + mfac * rt2[1]; + rt[2]= fac * rt1[2] + mfac * rt2[2]; + rt[3]= fac * rt1[3] + mfac * rt2[3]; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaunder_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_alphaunder_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_alphaunder_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + CROSS + ********************************************************************** */ + +void do_cross_effect_byte(float facf0, float facf1, int x, int y, + char *rect1, char *rect2, + char *out) +{ + int fac1, fac2, fac3, fac4; + int xo; + char *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= (int)(256.0*facf0); + fac1= 256-fac2; + fac4= (int)(256.0*facf1); + fac3= 256-fac4; + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8; + rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8; + rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8; + rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8; + rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8; + rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8; + rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + } +} + +void do_cross_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, float *out) +{ + float fac1, fac2, fac3, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac1= 1.0 - fac2; + fac4= facf1; + fac3= 1.0 - fac4; + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= fac1*rt1[0] + fac2*rt2[0]; + rt[1]= fac1*rt1[1] + fac2*rt2[1]; + rt[2]= fac1*rt1[2] + fac2*rt2[2]; + rt[3]= fac1*rt1[3] + fac2*rt2[3]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= fac3*rt1[0] + fac4*rt2[0]; + rt[1]= fac3*rt1[1] + fac4*rt2[1]; + rt[2]= fac3*rt1[2] + fac4*rt2[2]; + rt[3]= fac3*rt1[3] + fac4*rt2[3]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + } +} + +/* carefull: also used by speed effect! */ + +static void do_cross_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_cross_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_cross_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + GAMMA CROSS + ********************************************************************** */ + +/* copied code from initrender.c */ +static unsigned short gamtab[65536]; +static unsigned short igamtab1[256]; +static int gamma_tabs_init = FALSE; + +#define RE_GAMMA_TABLE_SIZE 400 + +static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1]; +static float color_step; +static float inv_color_step; +static float valid_gamma; +static float valid_inv_gamma; + +static void makeGammaTables(float gamma) +{ + /* we need two tables: one forward, one backward */ + int i; + + valid_gamma = gamma; + valid_inv_gamma = 1.0 / gamma; + color_step = 1.0 / RE_GAMMA_TABLE_SIZE; + inv_color_step = (float) RE_GAMMA_TABLE_SIZE; + + /* We could squeeze out the two range tables to gain some memory. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { + color_domain_table[i] = i * color_step; + gamma_range_table[i] = pow(color_domain_table[i], + valid_gamma); + inv_gamma_range_table[i] = pow(color_domain_table[i], + valid_inv_gamma); + } + + /* The end of the table should match 1.0 carefully. In order to avoid */ + /* rounding errors, we just set this explicitly. The last segment may */ + /* have a different lenght than the other segments, but our */ + /* interpolation is insensitive to that. */ + color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; + gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + + /* To speed up calculations, we make these calc factor tables. They are */ + /* multiplication factors used in scaling the interpolation. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) { + gamfactor_table[i] = inv_color_step + * (gamma_range_table[i + 1] - gamma_range_table[i]) ; + inv_gamfactor_table[i] = inv_color_step + * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ; + } + +} /* end of void makeGammaTables(float gamma) */ + + +static float gammaCorrect(float c) +{ + int i; + float res = 0.0; + + i = floor(c * inv_color_step); + /* Clip to range [0,1]: outside, just do the complete calculation. */ + /* We may have some performance problems here. Stretching up the LUT */ + /* may help solve that, by exchanging LUT size for the interpolation. */ + /* Negative colors are explicitly handled. */ + if (i < 0) res = -pow(abs(c), valid_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma); + else res = gamma_range_table[i] + + ( (c - color_domain_table[i]) * gamfactor_table[i]); + + return res; +} /* end of float gammaCorrect(float col) */ + +/* ------------------------------------------------------------------------- */ + +static float invGammaCorrect(float col) +{ + int i; + float res = 0.0; + + i = floor(col*inv_color_step); + /* Negative colors are explicitly handled. */ + if (i < 0) res = -pow(abs(col), valid_inv_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma); + else res = inv_gamma_range_table[i] + + ( (col - color_domain_table[i]) * inv_gamfactor_table[i]); + + return res; +} /* end of float invGammaCorrect(float col) */ + + +static void gamtabs(float gamma) +{ + float val, igamma= 1.0f/gamma; + int a; + + /* gamtab: in short, out short */ + for(a=0; a<65536; a++) { + val= a; + val/= 65535.0; + + if(gamma==2.0) val= sqrt(val); + else if(gamma!=1.0) val= pow(val, igamma); + + gamtab[a]= (65535.99*val); + } + /* inverse gamtab1 : in byte, out short */ + for(a=1; a<=256; a++) { + if(gamma==2.0) igamtab1[a-1]= a*a-1; + else if(gamma==1.0) igamtab1[a-1]= 256*a-1; + else { + val= a/256.0; + igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ; + } + } + +} + +static void build_gammatabs() +{ + if (gamma_tabs_init == FALSE) { + gamtabs(2.0f); + makeGammaTables(2.0f); + gamma_tabs_init = TRUE; + } +} + +static void init_gammacross(Sequence * seq) +{ +} + +static void load_gammacross(Sequence * seq) +{ +} + +static void free_gammacross(Sequence * seq) +{ +} + +static void do_gammacross_effect_byte(float facf0, float facf1, + int x, int y, + unsigned char *rect1, + unsigned char *rect2, + unsigned char *out) +{ + int fac1, fac2, col; + int xo; + unsigned char *rt1, *rt2, *rt; + + xo= x; + rt1= (unsigned char *)rect1; + rt2= (unsigned char *)rect2; + rt= (unsigned char *)out; + + fac2= (int)(256.0*facf0); + fac1= 256-fac2; + + while(y--) { + + x= xo; + while(x--) { + + col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; + if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; + if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; + if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; + if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; + if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; + if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; + if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; + if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } + +} + +static void do_gammacross_effect_float(float facf0, float facf1, + int x, int y, + float *rect1, float *rect2, + float *out) +{ + float fac1, fac2; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac1= 1.0 - fac2; + + while(y--) { + + x= xo * 4; + while(x--) { + + *rt= gammaCorrect( + fac1 * invGammaCorrect(*rt1) + + fac2 * invGammaCorrect(*rt2)); + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + + *rt= gammaCorrect( + fac1*invGammaCorrect(*rt1) + + fac2*invGammaCorrect(*rt2)); + + rt1++; rt2++; rt++; + } + } +} + +static void do_gammacross_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + build_gammatabs(); + + if (out->rect_float) { + do_gammacross_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_gammacross_effect_byte( + facf0, facf1, x, y, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); + } +} + + +/* ********************************************************************** + ADD + ********************************************************************** */ + +static void do_add_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect1, unsigned char *rect2, + unsigned char *out) +{ + int col, xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + col= rt1[0]+ ((fac1*rt2[0])>>8); + if(col>255) rt[0]= 255; else rt[0]= col; + col= rt1[1]+ ((fac1*rt2[1])>>8); + if(col>255) rt[1]= 255; else rt[1]= col; + col= rt1[2]+ ((fac1*rt2[2])>>8); + if(col>255) rt[2]= 255; else rt[2]= col; + col= rt1[3]+ ((fac1*rt2[3])>>8); + if(col>255) rt[3]= 255; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= rt1[0]+ ((fac3*rt2[0])>>8); + if(col>255) rt[0]= 255; else rt[0]= col; + col= rt1[1]+ ((fac3*rt2[1])>>8); + if(col>255) rt[1]= 255; else rt[1]= col; + col= rt1[2]+ ((fac3*rt2[2])>>8); + if(col>255) rt[2]= 255; else rt[2]= col; + col= rt1[3]+ ((fac3*rt2[3])>>8); + if(col>255) rt[3]= 255; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_add_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + while(y--) { + + x= xo * 4; + while(x--) { + *rt = *rt1 + fac1 * (*rt2); + + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + *rt = *rt1 + fac3 * (*rt2); + + rt1++; rt2++; rt++; + } + } +} + +static void do_add_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_add_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_add_effect_byte( + facf0, facf1, x, y, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); + } +} + + +/* ********************************************************************** + SUB + ********************************************************************** */ + +static void do_sub_effect_byte(float facf0, float facf1, + int x, int y, + char *rect1, char *rect2, char *out) +{ + int col, xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + col= rt1[0]- ((fac1*rt2[0])>>8); + if(col<0) rt[0]= 0; else rt[0]= col; + col= rt1[1]- ((fac1*rt2[1])>>8); + if(col<0) rt[1]= 0; else rt[1]= col; + col= rt1[2]- ((fac1*rt2[2])>>8); + if(col<0) rt[2]= 0; else rt[2]= col; + col= rt1[3]- ((fac1*rt2[3])>>8); + if(col<0) rt[3]= 0; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= rt1[0]- ((fac3*rt2[0])>>8); + if(col<0) rt[0]= 0; else rt[0]= col; + col= rt1[1]- ((fac3*rt2[1])>>8); + if(col<0) rt[1]= 0; else rt[1]= col; + col= rt1[2]- ((fac3*rt2[2])>>8); + if(col<0) rt[2]= 0; else rt[2]= col; + col= rt1[3]- ((fac3*rt2[3])>>8); + if(col<0) rt[3]= 0; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_sub_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + while(y--) { + + x= xo * 4; + while(x--) { + *rt = *rt1 - fac1 * (*rt2); + + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + *rt = *rt1 - fac3 * (*rt2); + + rt1++; rt2++; rt++; + } + } +} + +static void do_sub_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_sub_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_sub_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + DROP + ********************************************************************** */ + +/* Must be > 0 or add precopy, etc to the function */ +#define XOFF 8 +#define YOFF 8 + +static void do_drop_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect2i, unsigned char *rect1i, + unsigned char *outi) +{ + int height, width, temp, fac, fac1, fac2; + char *rt1, *rt2, *out; + int field= 1; + + width= x; + height= y; + + fac1= (int)(70.0*facf0); + fac2= (int)(70.0*facf1); + + rt2= (char*) (rect2i + YOFF*width); + rt1= (char*) rect1i; + out= (char*) outi; + for (y=0; y<height-YOFF; y++) { + if(field) fac= fac1; + else fac= fac2; + field= !field; + + memcpy(out, rt1, sizeof(int)*XOFF); + rt1+= XOFF*4; + out+= XOFF*4; + + for (x=XOFF; x<width; x++) { + temp= ((fac*rt2[3])>>8); + + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + rt2+=4; + } + rt2+=XOFF*4; + } + memcpy(out, rt1, sizeof(int)*YOFF*width); +} + +static void do_drop_effect_float(float facf0, float facf1, int x, int y, + float *rect2i, float *rect1i, + float *outi) +{ + int height, width; + float temp, fac, fac1, fac2; + float *rt1, *rt2, *out; + int field= 1; + + width= x; + height= y; + + fac1= 70.0*facf0; + fac2= 70.0*facf1; + + rt2= (rect2i + YOFF*width); + rt1= rect1i; + out= outi; + for (y=0; y<height-YOFF; y++) { + if(field) fac= fac1; + else fac= fac2; + field= !field; + + memcpy(out, rt1, 4 * sizeof(float)*XOFF); + rt1+= XOFF*4; + out+= XOFF*4; + + for (x=XOFF; x<width; x++) { + temp= fac * rt2[3]; + + *(out++)= MAX2(0.0, *rt1 - temp); rt1++; + *(out++)= MAX2(0.0, *rt1 - temp); rt1++; + *(out++)= MAX2(0.0, *rt1 - temp); rt1++; + *(out++)= MAX2(0.0, *rt1 - temp); rt1++; + rt2+=4; + } + rt2+=XOFF*4; + } + memcpy(out, rt1, 4 * sizeof(float)*YOFF*width); +} + + +static void do_drop_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf * ibuf3, + struct ImBuf *out) +{ + if (out->rect_float) { + do_drop_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_drop_effect_byte( + facf0, facf1, x, y, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); + } +} + +/* ********************************************************************** + MUL + ********************************************************************** */ + +static void do_mul_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect1, unsigned char *rect2, + unsigned char *out) +{ + int xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + /* formula: + * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+axaux= c*px + py*s ;//+centx + yaux= -s*px + c*py;//+centy + */ + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16); + rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16); + rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16); + rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16); + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16); + rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16); + rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16); + rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16); + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_mul_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + /* formula: + * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a + */ + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0); + rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0); + rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0); + rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0); + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0); + rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0); + rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0); + rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0); + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_mul_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_mul_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_mul_effect_byte( + facf0, facf1, x, y, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); + } +} + +/* ********************************************************************** + WIPE + ********************************************************************** */ + +typedef struct WipeZone { + float angle; + int flip; + int xo, yo; + int width; + float invwidth; + float pythangle; +} WipeZone; + +static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo) +{ + wipezone->flip = (wipe->angle < 0); + wipezone->angle = pow(fabs(wipe->angle)/45.0f, log(xo)/log(2.0f)); + wipezone->xo = xo; + wipezone->yo = yo; + wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f)); + wipezone->pythangle = 1.0f/sqrt(wipe->angle*wipe->angle + 1.0f); + + if(wipe->wipetype == DO_SINGLE_WIPE) + wipezone->invwidth = 1.0f/wipezone->width; + else + wipezone->invwidth = 1.0f/(0.5f*wipezone->width); +} + +// This function calculates the blur band for the wipe effects +static float in_band(WipeZone *wipezone,float width,float dist,float perc,int side,int dir) +{ + float t1,t2,alpha,percwidth; + + if(width == 0) + return (float)side; + + if(side == 1) + percwidth = width * perc; + else + percwidth = width * (1 - perc); + + if(width < dist) + return side; + + t1 = dist * wipezone->invwidth; //percentange of width that is + t2 = wipezone->invwidth; //amount of alpha per % point + + if(side == 1) + alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe + else + alpha = (1-perc) - (t1*t2*100); + + if(dir == 0) + alpha = 1-alpha; + + return alpha; +} + +static float check_zone(WipeZone *wipezone, int x, int y, + Sequence *seq, float facf0) +{ + float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist; +/*some future stuff +float hyp3,hyp4,b4,b5 +*/ + float temp1,temp2,temp3,temp4; //some placeholder variables + int xo = wipezone->xo; + int yo = wipezone->yo; + float halfx = xo*0.5f; + float halfy = yo*0.5f; + float widthf,output=0; + WipeVars *wipe = (WipeVars *)seq->effectdata; + int width; + + if(wipezone->flip) x = xo - x; + angle = wipezone->angle; + + posy = facf0 * yo; + + if(wipe->forward){ + posx = facf0 * xo; + posy = facf0 * yo; + } else{ + posx = xo - facf0 * xo; + posy = yo - facf0 * yo; + } + + switch (wipe->wipetype) { + case DO_SINGLE_WIPE: + width = wipezone->width; + hwidth = width*0.5f; + + if(angle == 0.0f) { + b1 = posy; + b2 = y; + hyp = fabs(y - posy); + } + else { + b1 = posy - (-angle)*posx; + b2 = y - (-angle)*x; + hyp = fabs(angle*x+y+(-posy-angle*posx))*wipezone->pythangle; + } + + if(angle < 0) { + temp1 = b1; + b1 = b2; + b2 = temp1; + } + + if(wipe->forward) { + if(b1 < b2) + output = in_band(wipezone,width,hyp,facf0,1,1); + else + output = in_band(wipezone,width,hyp,facf0,0,1); + } + else { + if(b1 < b2) + output = in_band(wipezone,width,hyp,facf0,0,1); + else + output = in_band(wipezone,width,hyp,facf0,1,1); + } + break; + + case DO_DOUBLE_WIPE: + if(!wipe->forward) + facf0 = 1.0f-facf0; // Go the other direction + + width = wipezone->width; // calculate the blur width + hwidth = width*0.5f; + if (angle == 0) { + b1 = posy*0.5f; + b3 = yo-posy*0.5f; + b2 = y; + + hyp = abs(y - posy*0.5f); + hyp2 = abs(y - (yo-posy*0.5f)); + } + else { + b1 = posy*0.5f - (-angle)*posx*0.5f; + b3 = (yo-posy*0.5f) - (-angle)*(xo-posx*0.5f); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy*0.5f-angle*posx*0.5f))*wipezone->pythangle; + hyp2 = abs(angle*x+y+(-(yo-posy*0.5f)-angle*(xo-posx*0.5f)))*wipezone->pythangle; + } + + temp1 = xo*(1-facf0*0.5f)-xo*facf0*0.5f; + temp2 = yo*(1-facf0*0.5f)-yo*facf0*0.5f; + pointdist = sqrt(temp1*temp1 + temp2*temp2); + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output = in_band(wipezone,hwidth,hyp,facf0,0,1); + } else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output = in_band(wipezone,hwidth,hyp2,facf0,0,1); + } else { + if( hyp < hwidth && hyp2 > hwidth ) + output = in_band(wipezone,hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output = in_band(wipezone,hwidth,hyp2,facf0,1,1); + else + output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1); + } + if(!wipe->forward)output = 1-output; + break; + case DO_CLOCK_WIPE: + /* + temp1: angle of effect center in rads + temp2: angle of line through (halfx,halfy) and (x,y) in rads + temp3: angle of low side of blur + temp4: angle of high side of blur + */ + output = 1.0f - facf0; + widthf = wipe->edgeWidth*2.0f*(float)M_PI; + temp1 = 2.0f * (float)M_PI * facf0; + + if(wipe->forward){ + temp1 = 2.0f*(float)M_PI - temp1; + } + + x = x - halfx; + y = y - halfy; + + temp2 = asin(abs(y)/sqrt(x*x + y*y)); + if(x <= 0 && y >= 0) temp2 = (float)M_PI - temp2; + else if(x<=0 && y <= 0) temp2 += (float)M_PI; + else if(x >= 0 && y <= 0) temp2 = 2.0f*(float)M_PI - temp2; + + if(wipe->forward){ + temp3 = temp1-(widthf*0.5f)*facf0; + temp4 = temp1+(widthf*0.5f)*(1-facf0); + } else{ + temp3 = temp1-(widthf*0.5f)*(1-facf0); + temp4 = temp1+(widthf*0.5f)*facf0; + } + if (temp3 < 0) temp3 = 0; + if (temp4 > 2.0f*(float)M_PI) temp4 = 2.0f*(float)M_PI; + + + if(temp2 < temp3) output = 0; + else if (temp2 > temp4) output = 1; + else output = (temp2-temp3)/(temp4-temp3); + if(x == 0 && y == 0) output = 1; + if(output != output) output = 1; + if(wipe->forward) output = 1 - output; + break; + /* BOX WIPE IS NOT WORKING YET */ + /* case DO_CROSS_WIPE: */ + /* BOX WIPE IS NOT WORKING YET */ + /* + case DO_BOX_WIPE: + if(invert)facf0 = 1-facf0; + + width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); + hwidth = (float)width/2.0; + if (angle == 0)angle = 0.000001; + b1 = posy/2 - (-angle)*posx/2; + b3 = (yo-posy/2) - (-angle)*(xo-posx/2); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle; + hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle; + + temp1 = xo*(1-facf0/2)-xo*facf0/2; + temp2 = yo*(1-facf0/2)-yo*facf0/2; + pointdist = sqrt(temp1*temp1 + temp2*temp2); + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output = in_band(wipezone,hwidth,hyp,facf0,0,1); + } else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output = in_band(wipezone,hwidth,hyp2,facf0,0,1); + } else { + if( hyp < hwidth && hyp2 > hwidth ) + output = in_band(wipezone,hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output = in_band(wipezone,hwidth,hyp2,facf0,1,1); + else + output = in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1); + } + + if(invert)facf0 = 1-facf0; + angle = -1/angle; + b1 = posy/2 - (-angle)*posx/2; + b3 = (yo-posy/2) - (-angle)*(xo-posx/2); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy/2-angle*posx/2))*wipezone->pythangle; + hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))*wipezone->pythangle; + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output *= in_band(wipezone,hwidth,hyp,facf0,0,1); + } else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output *= in_band(wipezone,hwidth,hyp2,facf0,0,1); + } else { + if( hyp < hwidth && hyp2 > hwidth ) + output *= in_band(wipezone,hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output *= in_band(wipezone,hwidth,hyp2,facf0,1,1); + else + output *= in_band(wipezone,hwidth,hyp2,facf0,1,1) * in_band(wipezone,hwidth,hyp,facf0,1,1); + } + + break; +*/ + case DO_IRIS_WIPE: + if(xo > yo) yo = xo; + else xo = yo; + + if(!wipe->forward) facf0 = 1-facf0; + + width = wipezone->width; + hwidth = width*0.5f; + + temp1 = (halfx-(halfx)*facf0); + pointdist = sqrt(temp1*temp1 + temp1*temp1); + + temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y)); + if(temp2 > pointdist) output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,0,1); + else output = in_band(wipezone,hwidth,fabs(temp2-pointdist),facf0,1,1); + + if(!wipe->forward) output = 1-output; + + break; + } + if (output < 0) output = 0; + else if(output > 1) output = 1; + return output; +} + +static void init_wipe_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars"); +} + +static int num_inputs_wipe() +{ + return 1; +} + +static void free_wipe_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_wipe_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, + int x, int y, + unsigned char *rect1, + unsigned char *rect2, unsigned char *out) +{ + WipeZone wipezone; + WipeVars *wipe = (WipeVars *)seq->effectdata; + int xo, yo; + char *rt1, *rt2, *rt; + + precalc_wipe_zone(&wipezone, wipe, x, y); + + rt1 = (char *)rect1; + rt2 = (char *)rect2; + rt = (char *)out; + + xo = x; + yo = y; + for(y=0;y<yo;y++) { + for(x=0;x<xo;x++) { + float check = check_zone(&wipezone,x,y,seq,facf0); + if (check) { + if (rt1) { + rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check)); + rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check)); + rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check)); + rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check)); + } else { + rt[0] = 0; + rt[1] = 0; + rt[2] = 0; + rt[3] = 255; + } + } else { + if (rt2) { + rt[0] = rt2[0]; + rt[1] = rt2[1]; + rt[2] = rt2[2]; + rt[3] = rt2[3]; + } else { + rt[0] = 0; + rt[1] = 0; + rt[2] = 0; + rt[3] = 255; + } + } + + rt+=4; + if(rt1 !=NULL){ + rt1+=4; + } + if(rt2 !=NULL){ + rt2+=4; + } + } + } +} + +static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1, + int x, int y, + float *rect1, + float *rect2, float *out) +{ + WipeZone wipezone; + WipeVars *wipe = (WipeVars *)seq->effectdata; + int xo, yo; + float *rt1, *rt2, *rt; + + precalc_wipe_zone(&wipezone, wipe, x, y); + + rt1 = rect1; + rt2 = rect2; + rt = out; + + xo = x; + yo = y; + for(y=0;y<yo;y++) { + for(x=0;x<xo;x++) { + float check = check_zone(&wipezone,x,y,seq,facf0); + if (check) { + if (rt1) { + rt[0] = rt1[0]*check+ rt2[0]*(1-check); + rt[1] = rt1[1]*check+ rt2[1]*(1-check); + rt[2] = rt1[2]*check+ rt2[2]*(1-check); + rt[3] = rt1[3]*check+ rt2[3]*(1-check); + } else { + rt[0] = 0; + rt[1] = 0; + rt[2] = 0; + rt[3] = 1.0; + } + } else { + if (rt2) { + rt[0] = rt2[0]; + rt[1] = rt2[1]; + rt[2] = rt2[2]; + rt[3] = rt2[3]; + } else { + rt[0] = 0; + rt[1] = 0; + rt[2] = 0; + rt[3] = 1.0; + } + } + + rt+=4; + if(rt1 !=NULL){ + rt1+=4; + } + if(rt2 !=NULL){ + rt2+=4; + } + } + } +} + +static void do_wipe_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_wipe_effect_float(seq, + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_wipe_effect_byte(seq, + facf0, facf1, x, y, + (unsigned char*) ibuf1->rect, (unsigned char*) ibuf2->rect, + (unsigned char*) out->rect); + } +} +/* ********************************************************************** + TRANSFORM + ********************************************************************** */ +static void init_transform_effect(Sequence *seq) +{ + TransformVars *scale; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct TransformVars), "transformvars"); + + scale = (TransformVars *)seq->effectdata; + scale->ScalexIni = 1; + scale->ScaleyIni = 1; + scale->ScalexFin = 1; + scale->ScaleyFin = 1; + + scale->xIni=0; + scale->xFin=0; + scale->yIni=0; + scale->yFin=0; + + scale->rotIni=0; + scale->rotFin=0; + + scale->interpolation=1; + scale->percent=1; +} + +static int num_inputs_transform() +{ + return 1; +} + +static void free_transform_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_transform_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static void do_transform(Sequence * seq,float facf0, int x, int y, + struct ImBuf *ibuf1,struct ImBuf *out) +{ + int xo, yo, xi, yi; + float xs,ys,factxScale,factyScale,tx,ty,rad,s,c,xaux,yaux,factRot,px,py; + TransformVars *scale; + + // XXX struct RenderData *rd = NULL; // 2.5 global: &G.scene->r; + + + scale = (TransformVars *)seq->effectdata; + xo = x; + yo = y; + + //factor scale + factxScale = scale->ScalexIni + (scale->ScalexFin - scale->ScalexIni) * facf0; + factyScale = scale->ScaleyIni + (scale->ScaleyFin - scale->ScaleyIni) * facf0; + + //Factor translate + if(!scale->percent){ + float rd_s = 0.0f; // XXX 2.5 global: (rd->size / 100.0f); + + tx = scale->xIni * rd_s+(xo / 2.0f) + (scale->xFin * rd_s -(xo / 2.0f) - scale->xIni * rd_s +(xo / 2.0f)) * facf0; + ty = scale->yIni * rd_s+(yo / 2.0f) + (scale->yFin * rd_s -(yo / 2.0f) - scale->yIni * rd_s +(yo / 2.0f)) * facf0; + }else{ + tx = xo*(scale->xIni/100.0f)+(xo / 2.0f) + (xo*(scale->xFin/100.0f)-(xo / 2.0f) - xo*(scale->xIni/100.0f)+(xo / 2.0f)) * facf0; + ty = yo*(scale->yIni/100.0f)+(yo / 2.0f) + (yo*(scale->yFin/100.0f)-(yo / 2.0f) - yo*(scale->yIni/100.0f)+(yo / 2.0f)) * facf0; + } + + //factor Rotate + factRot = scale->rotIni + (scale->rotFin - scale->rotIni) * facf0; + rad = (M_PI * factRot) / 180.0f; + s= sin(rad); + c= cos(rad); + + + for (yi = 0; yi < yo; yi++) { + for (xi = 0; xi < xo; xi++) { + //tranlate point + px = xi-tx; + py = yi-ty; + + //rotate point with center ref + xaux = c*px + py*s ; + yaux = -s*px + c*py; + + //scale point with center ref + xs = xaux / factxScale; + ys = yaux / factyScale; + + //undo reference center point + xs += (xo / 2.0f); + ys += (yo / 2.0f); + + //interpolate + switch(scale->interpolation) { + case 0: + neareast_interpolation(ibuf1,out, xs,ys,xi,yi); + break; + case 1: + bilinear_interpolation(ibuf1,out, xs,ys,xi,yi); + break; + case 2: + bicubic_interpolation(ibuf1,out, xs,ys,xi,yi); + break; + } + } + } + +} +static void do_transform_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + do_transform(seq, facf0, x, y, ibuf1, out); +} + + +/* ********************************************************************** + GLOW + ********************************************************************** */ + +static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height, + float blur, + int quality) +/* MUUUCCH better than the previous blur. */ +/* We do the blurring in two passes which is a whole lot faster. */ +/* I changed the math arount to implement an actual Gaussian */ +/* distribution. */ +/* */ +/* Watch out though, it tends to misbehaven with large blur values on */ +/* a small bitmap. Avoid avoid avoid. */ +/*=============================== */ +{ + unsigned char* temp=NULL,*swap; + float *filter=NULL; + int x,y,i,fx,fy; + int index, ix, halfWidth; + float fval, k, curColor[3], curColor2[3], weight=0; + + /* If we're not really blurring, bail out */ + if (blur<=0) + return; + + /* Allocate memory for the tempmap and the blur filter matrix */ + temp= MEM_mallocN( (width*height*4), "blurbitmaptemp"); + if (!temp) + return; + + /* Allocate memory for the filter elements */ + halfWidth = ((quality+1)*blur); + filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter"); + if (!filter){ + MEM_freeN (temp); + return; + } + + /* Apparently we're calculating a bell curve */ + /* based on the standard deviation (or radius) */ + /* This code is based on an example */ + /* posted to comp.graphics.algorithms by */ + /* Blancmange (bmange@airdmhor.gen.nz) */ + + k = -1.0/(2.0*3.14159*blur*blur); + fval=0; + for (ix = 0;ix< halfWidth;ix++){ + weight = (float)exp(k*(ix*ix)); + filter[halfWidth - ix] = weight; + filter[halfWidth + ix] = weight; + } + filter[0] = weight; + + /* Normalize the array */ + fval=0; + for (ix = 0;ix< halfWidth*2;ix++) + fval+=filter[ix]; + + for (ix = 0;ix< halfWidth*2;ix++) + filter[ix]/=fval; + + /* Blur the rows */ + for (y=0;y<height;y++){ + /* Do the left & right strips */ + for (x=0;x<halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0; + curColor2[0]=curColor2[1]=curColor2[2]=0; + + for (i=x-halfWidth;i<x+halfWidth;i++){ + if ((i>=0)&&(i<width)){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + + curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] * + filter[fx]; + curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] * + filter[fx]; + curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] * + filter[fx]; + } + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + + temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0]; + temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1]; + temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2]; + + } + /* Do the main body */ + for (x=halfWidth;x<width-halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=x-halfWidth;i<x+halfWidth;i++){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + + /* Blur the columns */ + for (x=0;x<width;x++){ + /* Do the top & bottom strips */ + for (y=0;y<halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + curColor2[0]=curColor2[1]=curColor2[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + if ((i>=0)&&(i<height)){ + /* Bottom */ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + + /* Top */ + curColor2[0]+=map[(x+(height-1-i)*width) * + 4+GlowR]*filter[fy]; + curColor2[1]+=map[(x+(height-1-i)*width) * + 4+GlowG]*filter[fy]; + curColor2[2]+=map[(x+(height-1-i)*width) * + 4+GlowB]*filter[fy]; + } + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0]; + temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1]; + temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2]; + } + /* Do the main body */ + for (y=halfWidth;y<height-halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + /* Tidy up */ + MEM_freeN (filter); + MEM_freeN (temp); +} + +static void RVBlurBitmap2_float ( float* map, int width,int height, + float blur, + int quality) +/* MUUUCCH better than the previous blur. */ +/* We do the blurring in two passes which is a whole lot faster. */ +/* I changed the math arount to implement an actual Gaussian */ +/* distribution. */ +/* */ +/* Watch out though, it tends to misbehaven with large blur values on */ +/* a small bitmap. Avoid avoid avoid. */ +/*=============================== */ +{ + float* temp=NULL,*swap; + float *filter=NULL; + int x,y,i,fx,fy; + int index, ix, halfWidth; + float fval, k, curColor[3], curColor2[3], weight=0; + + /* If we're not really blurring, bail out */ + if (blur<=0) + return; + + /* Allocate memory for the tempmap and the blur filter matrix */ + temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp"); + if (!temp) + return; + + /* Allocate memory for the filter elements */ + halfWidth = ((quality+1)*blur); + filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter"); + if (!filter){ + MEM_freeN (temp); + return; + } + + /* Apparently we're calculating a bell curve */ + /* based on the standard deviation (or radius) */ + /* This code is based on an example */ + /* posted to comp.graphics.algorithms by */ + /* Blancmange (bmange@airdmhor.gen.nz) */ + + k = -1.0/(2.0*3.14159*blur*blur); + fval=0; + for (ix = 0;ix< halfWidth;ix++){ + weight = (float)exp(k*(ix*ix)); + filter[halfWidth - ix] = weight; + filter[halfWidth + ix] = weight; + } + filter[0] = weight; + + /* Normalize the array */ + fval=0; + for (ix = 0;ix< halfWidth*2;ix++) + fval+=filter[ix]; + + for (ix = 0;ix< halfWidth*2;ix++) + filter[ix]/=fval; + + /* Blur the rows */ + for (y=0;y<height;y++){ + /* Do the left & right strips */ + for (x=0;x<halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0.0f; + curColor2[0]=curColor2[1]=curColor2[2]=0.0f; + + for (i=x-halfWidth;i<x+halfWidth;i++){ + if ((i>=0)&&(i<width)){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + + curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] * + filter[fx]; + curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] * + filter[fx]; + curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] * + filter[fx]; + } + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + + temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0]; + temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1]; + temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2]; + + } + /* Do the main body */ + for (x=halfWidth;x<width-halfWidth;x++){ + index=(x+y*width)*4; + fx=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=x-halfWidth;i<x+halfWidth;i++){ + curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx]; + curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx]; + curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx]; + fx++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + + /* Blur the columns */ + for (x=0;x<width;x++){ + /* Do the top & bottom strips */ + for (y=0;y<halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + curColor2[0]=curColor2[1]=curColor2[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + if ((i>=0)&&(i<height)){ + /* Bottom */ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + + /* Top */ + curColor2[0]+=map[(x+(height-1-i)*width) * + 4+GlowR]*filter[fy]; + curColor2[1]+=map[(x+(height-1-i)*width) * + 4+GlowG]*filter[fy]; + curColor2[2]+=map[(x+(height-1-i)*width) * + 4+GlowB]*filter[fy]; + } + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0]; + temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1]; + temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2]; + } + /* Do the main body */ + for (y=halfWidth;y<height-halfWidth;y++){ + index=(x+y*width)*4; + fy=0; + curColor[0]=curColor[1]=curColor[2]=0; + for (i=y-halfWidth;i<y+halfWidth;i++){ + curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy]; + curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy]; + curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy]; + fy++; + } + temp[index+GlowR]=curColor[0]; + temp[index+GlowG]=curColor[1]; + temp[index+GlowB]=curColor[2]; + } + } + + + /* Swap buffers */ + swap=temp;temp=map;map=swap; + + /* Tidy up */ + MEM_freeN (filter); + MEM_freeN (temp); +} + + +/* Adds two bitmaps and puts the results into a third map. */ +/* C must have been previously allocated but it may be A or B. */ +/* We clamp values to 255 to prevent weirdness */ +/*=============================== */ +static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height) +{ + int x,y,index; + + for (y=0;y<height;y++){ + for (x=0;x<width;x++){ + index=(x+y*width)*4; + c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]); + c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]); + c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]); + c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]); + } + } +} + +static void RVAddBitmaps_float (float* a, float* b, float* c, + int width, int height) +{ + int x,y,index; + + for (y=0;y<height;y++){ + for (x=0;x<width;x++){ + index=(x+y*width)*4; + c[index+GlowR]=MIN2(1.0,a[index+GlowR]+b[index+GlowR]); + c[index+GlowG]=MIN2(1.0,a[index+GlowG]+b[index+GlowG]); + c[index+GlowB]=MIN2(1.0,a[index+GlowB]+b[index+GlowB]); + c[index+GlowA]=MIN2(1.0,a[index+GlowA]+b[index+GlowA]); + } + } +} + +/* For each pixel whose total luminance exceeds the threshold, */ +/* Multiply it's value by BOOST and add it to the output map */ +static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out, + int width, int height, int threshold, + float boost, float clamp) +{ + int x,y,index; + int intensity; + + + for(y=0;y< height;y++) { + for (x=0;x< width;x++) { + index= (x+y*width)*4; + + /* Isolate the intensity */ + intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold); + if (intensity>0){ + out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255); + out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255); + out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255); + out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255); + } else{ + out[index+GlowR]=0; + out[index+GlowG]=0; + out[index+GlowB]=0; + out[index+GlowA]=0; + } + } + } +} + +static void RVIsolateHighlights_float (float* in, float* out, + int width, int height, float threshold, + float boost, float clamp) +{ + int x,y,index; + float intensity; + + + for(y=0;y< height;y++) { + for (x=0;x< width;x++) { + index= (x+y*width)*4; + + /* Isolate the intensity */ + intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold); + if (intensity>0){ + out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity)); + out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity)); + out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity)); + out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity)); + } else{ + out[index+GlowR]=0; + out[index+GlowG]=0; + out[index+GlowB]=0; + out[index+GlowA]=0; + } + } + } +} + +static void init_glow_effect(Sequence *seq) +{ + GlowVars *glow; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars"); + + glow = (GlowVars *)seq->effectdata; + glow->fMini = 0.25; + glow->fClamp = 1.0; + glow->fBoost = 0.5; + glow->dDist = 3.0; + glow->dQuality = 3; + glow->bNoComp = 0; +} + +static int num_inputs_glow() +{ + return 1; +} + +static void free_glow_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_glow_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) +static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, + int x, int y, char *rect1, + char *rect2, char *out) +{ + unsigned char *outbuf=(unsigned char *)out; + unsigned char *inbuf=(unsigned char *)rect1; + GlowVars *glow = (GlowVars *)seq->effectdata; + int size= 100; // renderdata XXX + + RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost * facf0, glow->fClamp); + RVBlurBitmap2_byte (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality); + if (!glow->bNoComp) + RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y); +} + +static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, + int x, int y, + float *rect1, float *rect2, float *out) +{ + float *outbuf = out; + float *inbuf = rect1; + GlowVars *glow = (GlowVars *)seq->effectdata; + int size= 100; // renderdata XXX + + RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*3.0f, glow->fBoost * facf0, glow->fClamp); + RVBlurBitmap2_float (outbuf, x, y, glow->dDist * (size / 100.0f),glow->dQuality); + if (!glow->bNoComp) + RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y); +} + +static void do_glow_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_glow_effect_float(seq, + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_glow_effect_byte(seq, + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + SOLID COLOR + ********************************************************************** */ + +static void init_solid_color(Sequence *seq) +{ + SolidColorVars *cv; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct SolidColorVars), "solidcolor"); + + cv = (SolidColorVars *)seq->effectdata; + cv->col[0] = cv->col[1] = cv->col[2] = 0.5; +} + +static int num_inputs_color() +{ + return 0; +} + +static void free_solid_color(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_solid_color(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static int early_out_color(struct Sequence *seq, + float facf0, float facf1) +{ + return -1; +} + +static void do_solid_color(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + SolidColorVars *cv = (SolidColorVars *)seq->effectdata; + + unsigned char *rect; + float *rect_float; + + if (out->rect) { + unsigned char col0[3]; + unsigned char col1[3]; + + col0[0] = facf0 * cv->col[0] * 255; + col0[1] = facf0 * cv->col[1] * 255; + col0[2] = facf0 * cv->col[2] * 255; + + col1[0] = facf1 * cv->col[0] * 255; + col1[1] = facf1 * cv->col[1] * 255; + col1[2] = facf1 * cv->col[2] * 255; + + rect = (unsigned char *)out->rect; + + for(y=0; y<out->y; y++) { + for(x=0; x<out->x; x++, rect+=4) { + rect[0]= col0[0]; + rect[1]= col0[1]; + rect[2]= col0[2]; + rect[3]= 255; + } + y++; + if (y<out->y) { + for(x=0; x<out->x; x++, rect+=4) { + rect[0]= col1[0]; + rect[1]= col1[1]; + rect[2]= col1[2]; + rect[3]= 255; + } + } + } + + } else if (out->rect_float) { + float col0[3]; + float col1[3]; + + col0[0] = facf0 * cv->col[0]; + col0[1] = facf0 * cv->col[1]; + col0[2] = facf0 * cv->col[2]; + + col1[0] = facf1 * cv->col[0]; + col1[1] = facf1 * cv->col[1]; + col1[2] = facf1 * cv->col[2]; + + rect_float = out->rect_float; + + for(y=0; y<out->y; y++) { + for(x=0; x<out->x; x++, rect_float+=4) { + rect_float[0]= col0[0]; + rect_float[1]= col0[1]; + rect_float[2]= col0[2]; + rect_float[3]= 1.0; + } + y++; + if (y<out->y) { + for(x=0; x<out->x; x++, rect_float+=4) { + rect_float[0]= col1[0]; + rect_float[1]= col1[1]; + rect_float[2]= col1[2]; + rect_float[3]= 1.0; + } + } + } + } +} + +/* ********************************************************************** + SPEED + ********************************************************************** */ +static void init_speed_effect(Sequence *seq) +{ + SpeedControlVars * v; + + if(seq->effectdata) MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct SpeedControlVars), + "speedcontrolvars"); + + v = (SpeedControlVars *)seq->effectdata; + v->globalSpeed = 1.0; + v->frameMap = 0; + v->flags = SEQ_SPEED_COMPRESS_IPO_Y; + v->length = 0; +} + +static void load_speed_effect(Sequence * seq) +{ + SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; + + v->frameMap = 0; + v->length = 0; +} + +static int num_inputs_speed() +{ + return 1; +} + +static void free_speed_effect(Sequence *seq) +{ + SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; + if(v->frameMap) MEM_freeN(v->frameMap); + if(seq->effectdata) MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_speed_effect(Sequence *dst, Sequence *src) +{ + SpeedControlVars * v; + dst->effectdata = MEM_dupallocN(src->effectdata); + v = (SpeedControlVars *)dst->effectdata; + v->frameMap = 0; + v->length = 0; +} + +static int early_out_speed(struct Sequence *seq, + float facf0, float facf1) +{ + return 1; +} + +static void store_icu_yrange_speed(struct Sequence * seq, + short adrcode, float * ymin, float * ymax) +{ + SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; + + /* if not already done, load / initialize data */ + get_sequence_effect(seq); + + if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { + *ymin = -100.0; + *ymax = 100.0; + } else { + if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { + *ymin = 0.0; + *ymax = 1.0; + } else { + *ymin = 0.0; + *ymax = seq->len; + } + } +} + +void sequence_effect_speed_rebuild_map(Sequence * seq, int force) +{ + float facf0 = seq->facf0; + //float ctime, div; + int cfra; + float fallback_fac; + SpeedControlVars * v = (SpeedControlVars *)seq->effectdata; + + /* if not already done, load / initialize data */ + get_sequence_effect(seq); + + if (!(force || seq->len != v->length || !v->frameMap)) { + return; + } + + if (!v->frameMap || v->length != seq->len) { + if (v->frameMap) MEM_freeN(v->frameMap); + + v->length = seq->len; + + v->frameMap = MEM_callocN(sizeof(float) * v->length, + "speedcontrol frameMap"); + } + + fallback_fac = 1.0; + + /* if there is no IPO, try to make retiming easy by stretching the + strip */ + // XXX old animation system - seq + if (/*!seq->ipo &&*/ seq->seq1 && seq->seq1->enddisp != seq->seq1->start + && seq->seq1->len != 0) { + fallback_fac = (float) seq->seq1->len / + (float) (seq->seq1->enddisp - seq->seq1->start); + /* FIXME: this strip stretching gets screwed by stripdata + handling one layer up. + + So it currently works by enlarging, never by shrinking! + + (IPOs still work, if used correctly) + */ + if (fallback_fac > 1.0) { + fallback_fac = 1.0; + } + } + + if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) { + float cursor = 0; + + v->frameMap[0] = 0; + v->lastValidFrame = 0; + + for (cfra = 1; cfra < v->length; cfra++) { +#if 0 // XXX old animation system + if(seq->ipo) { + if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) { + ctime = frame_to_float(scene, seq->startdisp + cfra); + div = 1.0; + } else { + ctime= frame_to_float(scene, cfra); + div= v->length / 100.0f; + if(div==0.0) return; + } + + calc_ipo(seq->ipo, ctime/div); + execute_ipo((ID *)seq, seq->ipo); + } else +#endif // XXX old animation system + { + seq->facf0 = fallback_fac; + } + seq->facf0 *= v->globalSpeed; + + cursor += seq->facf0; + + if (cursor >= v->length) { + v->frameMap[cfra] = v->length - 1; + } else { + v->frameMap[cfra] = cursor; + v->lastValidFrame = cfra; + } + } + } else { + v->lastValidFrame = 0; + for (cfra = 0; cfra < v->length; cfra++) { +#if 0 // XXX old animation system + if(seq->ipo) { + if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) { + ctime = frame_to_float(scene, seq->startdisp + cfra); + div = 1.0; + } else { + ctime= frame_to_float(scene, cfra); + div= v->length / 100.0f; + if(div==0.0) return; + } + + calc_ipo(seq->ipo, ctime/div); + execute_ipo((ID *)seq, seq->ipo); + } +#endif // XXX old animation system + + if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) { + seq->facf0 *= v->length; + } + if (/*!seq->ipo*/ 1) { // XXX old animation system - seq + seq->facf0 = (float) cfra * fallback_fac; + } + seq->facf0 *= v->globalSpeed; + if (seq->facf0 >= v->length) { + seq->facf0 = v->length - 1; + } else { + v->lastValidFrame = cfra; + } + v->frameMap[cfra] = seq->facf0; + } + } + seq->facf0 = facf0; +} + +/* + simply reuse do_cross_effect for blending... + +static void do_speed_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + +} +*/ + + +/* ********************************************************************** + sequence effect factory + ********************************************************************** */ + + +static void init_noop(struct Sequence *seq) +{ + +} + +static void load_noop(struct Sequence *seq) +{ + +} + +static void init_plugin_noop(struct Sequence *seq, const char * fname) +{ + +} + +static void free_noop(struct Sequence *seq) +{ + +} + +static int num_inputs_default() +{ + return 2; +} + +static int early_out_noop(struct Sequence *seq, + float facf0, float facf1) +{ + return 0; +} + +static int early_out_fade(struct Sequence *seq, + float facf0, float facf1) +{ + if (facf0 == 0.0 && facf1 == 0.0) { + return 1; + } else if (facf0 == 1.0 && facf1 == 1.0) { + return 2; + } + return 0; +} + +static int early_out_mul_input2(struct Sequence *seq, + float facf0, float facf1) +{ + if (facf0 == 0.0 && facf1 == 0.0) { + return 1; + } + return 0; +} + +static void store_icu_yrange_noop(struct Sequence * seq, + short adrcode, float * ymin, float * ymax) +{ + /* defaults are fine */ +} + +static void get_default_fac_noop(struct Sequence *seq, int cfra, + float * facf0, float * facf1) +{ + *facf0 = *facf1 = 1.0; +} + +static void get_default_fac_fade(struct Sequence *seq, int cfra, + float * facf0, float * facf1) +{ + *facf0 = (float)(cfra - seq->startdisp); + *facf1 = (float)(*facf0 + 0.5); + *facf0 /= seq->len; + *facf1 /= seq->len; +} + +static void do_overdrop_effect(struct Sequence * seq, int cfra, + float fac, float facf, + int x, int y, struct ImBuf * ibuf1, + struct ImBuf * ibuf2, + struct ImBuf * ibuf3, + struct ImBuf * out) +{ + do_drop_effect(seq, cfra, fac, facf, x, y, + ibuf1, ibuf2, ibuf3, out); + do_alphaover_effect(seq, cfra, fac, facf, x, y, + ibuf1, ibuf2, ibuf3, out); +} + +static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) +{ + struct SeqEffectHandle rval; + int sequence_type = seq_type; + + rval.init = init_noop; + rval.init_plugin = init_plugin_noop; + rval.num_inputs = num_inputs_default; + rval.load = load_noop; + rval.free = free_noop; + rval.early_out = early_out_noop; + rval.get_default_fac = get_default_fac_noop; + rval.store_icu_yrange = store_icu_yrange_noop; + rval.execute = NULL; + rval.copy = NULL; + + switch (sequence_type) { + case SEQ_CROSS: + rval.execute = do_cross_effect; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + break; + case SEQ_GAMCROSS: + rval.init = init_gammacross; + rval.load = load_gammacross; + rval.free = free_gammacross; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + rval.execute = do_gammacross_effect; + break; + case SEQ_ADD: + rval.execute = do_add_effect; + rval.early_out = early_out_mul_input2; + break; + case SEQ_SUB: + rval.execute = do_sub_effect; + rval.early_out = early_out_mul_input2; + break; + case SEQ_MUL: + rval.execute = do_mul_effect; + rval.early_out = early_out_mul_input2; + break; + case SEQ_ALPHAOVER: + rval.init = init_alpha_over_or_under; + rval.execute = do_alphaover_effect; + break; + case SEQ_OVERDROP: + rval.execute = do_overdrop_effect; + break; + case SEQ_ALPHAUNDER: + rval.init = init_alpha_over_or_under; + rval.execute = do_alphaunder_effect; + break; + case SEQ_WIPE: + rval.init = init_wipe_effect; + rval.num_inputs = num_inputs_wipe; + rval.free = free_wipe_effect; + rval.copy = copy_wipe_effect; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + rval.execute = do_wipe_effect; + break; + case SEQ_GLOW: + rval.init = init_glow_effect; + rval.num_inputs = num_inputs_glow; + rval.free = free_glow_effect; + rval.copy = copy_glow_effect; + rval.execute = do_glow_effect; + break; + case SEQ_TRANSFORM: + rval.init = init_transform_effect; + rval.num_inputs = num_inputs_transform; + rval.free = free_transform_effect; + rval.copy = copy_transform_effect; + rval.execute = do_transform_effect; + break; + case SEQ_SPEED: + rval.init = init_speed_effect; + rval.num_inputs = num_inputs_speed; + rval.load = load_speed_effect; + rval.free = free_speed_effect; + rval.copy = copy_speed_effect; + rval.execute = do_cross_effect; + rval.early_out = early_out_speed; + rval.store_icu_yrange = store_icu_yrange_speed; + break; + case SEQ_COLOR: + rval.init = init_solid_color; + rval.num_inputs = num_inputs_color; + rval.early_out = early_out_color; + rval.free = free_solid_color; + rval.copy = copy_solid_color; + rval.execute = do_solid_color; + break; + case SEQ_PLUGIN: + rval.init_plugin = init_plugin; + rval.num_inputs = num_inputs_plugin; + rval.load = load_plugin; + rval.free = free_plugin; + rval.copy = copy_plugin; + rval.execute = do_plugin_effect; + rval.early_out = do_plugin_early_out; + rval.get_default_fac = get_default_fac_fade; + break; + } + + return rval; +} + + +struct SeqEffectHandle get_sequence_effect(Sequence * seq) +{ + struct SeqEffectHandle rval; + + memset(&rval, 0, sizeof(struct SeqEffectHandle)); + + if (seq->type & SEQ_EFFECT) { + rval = get_sequence_effect_impl(seq->type); + if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) { + rval.load(seq); + seq->flag &= ~SEQ_EFFECT_NOT_LOADED; + } + } + + return rval; +} + +struct SeqEffectHandle get_sequence_blend(Sequence * seq) +{ + struct SeqEffectHandle rval; + + memset(&rval, 0, sizeof(struct SeqEffectHandle)); + + if (seq->blend_mode != 0) { + rval = get_sequence_effect_impl(seq->blend_mode); + if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) { + rval.load(seq); + seq->flag &= ~SEQ_EFFECT_NOT_LOADED; + } + } + + return rval; +} + +int get_sequence_effect_num_inputs(int seq_type) +{ + struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type); + + int cnt = rval.num_inputs(); + if (rval.execute) { + return cnt; + } + return 0; +} diff --git a/source/blender/blenkernel/intern/sequence.c b/source/blender/blenkernel/intern/sequence.c new file mode 100644 index 00000000000..3365af36f8c --- /dev/null +++ b/source/blender/blenkernel/intern/sequence.c @@ -0,0 +1,3417 @@ +/** +* $Id: sequence.c 17508 2008-11-20 00:34:24Z campbellbarton $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): + * - Blender Foundation, 2003-2009 + * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" +#include "DNA_sequence_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_sequence.h" +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_threads.h" +#include <pthread.h> + +#ifdef WIN32 +#define snprintf _snprintf +#endif + +/* **** XXX ******** */ +static int seqrectx= 0; /* bad bad global! */ +static int seqrecty= 0; +static void waitcursor() {} +static int blender_test_break() {return 0;} + +/* **** XXX ******** */ + + +/* ********************************************************************** + alloc / free functions + ********************************************************************** */ + +static void free_tstripdata(int len, TStripElem *se) +{ + TStripElem *seo; + int a; + + seo= se; + if (!se) + return; + + for(a=0; a<len; a++, se++) { + if(se->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = 0; + } + if(se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + se->ibuf_comp = 0; + } + } + + MEM_freeN(seo); +} + + +void new_tstripdata(Sequence *seq) +{ + if(seq->strip) { + free_tstripdata(seq->strip->len, seq->strip->tstripdata); + free_tstripdata(seq->strip->endstill, + seq->strip->tstripdata_endstill); + free_tstripdata(seq->strip->startstill, + seq->strip->tstripdata_startstill); + + seq->strip->tstripdata= 0; + seq->strip->tstripdata_endstill= 0; + seq->strip->tstripdata_startstill= 0; + + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + seq->strip->len= seq->len; + } +} + + +/* free */ + +static void free_proxy_seq(Sequence *seq) +{ + if (seq->strip && seq->strip->proxy && seq->strip->proxy->anim) { + IMB_free_anim(seq->strip->proxy->anim); + seq->strip->proxy->anim = 0; + } +} + +void seq_free_strip(Strip *strip) +{ + strip->us--; + if(strip->us>0) return; + if(strip->us<0) { + printf("error: negative users in strip\n"); + return; + } + + if (strip->stripdata) { + MEM_freeN(strip->stripdata); + } + + if (strip->proxy) { + if (strip->proxy->anim) { + IMB_free_anim(strip->proxy->anim); + } + + MEM_freeN(strip->proxy); + } + if (strip->crop) { + MEM_freeN(strip->crop); + } + if (strip->transform) { + MEM_freeN(strip->transform); + } + if (strip->color_balance) { + MEM_freeN(strip->color_balance); + } + + free_tstripdata(strip->len, strip->tstripdata); + free_tstripdata(strip->endstill, strip->tstripdata_endstill); + free_tstripdata(strip->startstill, strip->tstripdata_startstill); + + if(strip->ibuf_startstill) { + IMB_freeImBuf(strip->ibuf_startstill); + strip->ibuf_startstill = 0; + } + + if(strip->ibuf_endstill) { + IMB_freeImBuf(strip->ibuf_endstill); + strip->ibuf_endstill = 0; + } + + MEM_freeN(strip); +} + +void seq_free_sequence(Editing *ed, Sequence *seq) +{ + if(seq->strip) seq_free_strip(seq->strip); + + if(seq->anim) IMB_free_anim(seq->anim); + //XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); + + /* XXX if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh = get_sequence_effect(seq); + + sh.free(seq); + }*/ + + if (ed->act_seq==seq) + ed->act_seq= NULL; + + MEM_freeN(seq); +} + +Editing *seq_give_editing(Scene *scene, int alloc) +{ + if (scene->ed == NULL && alloc) { + Editing *ed; + + ed= scene->ed= MEM_callocN( sizeof(Editing), "addseq"); + ed->seqbasep= &ed->seqbase; + } + return scene->ed; +} + +void seq_free_editing(Editing *ed) +{ + MetaStack *ms; + Sequence *seq; + + if(ed==NULL) + return; + + SEQ_BEGIN(ed, seq) { + seq_free_sequence(ed, seq); + } + SEQ_END + + while((ms= ed->metastack.first)) { + BLI_remlink(&ed->metastack, ms); + MEM_freeN(ms); + } + + MEM_freeN(ed); +} + +/* ************************* itterator ************************** */ +/* *************** (replaces old WHILE_SEQ) ********************* */ +/* **************** use now SEQ_BEGIN() SEQ_END ***************** */ + +/* sequence strip iterator: + * - builds a full array, recursively into meta strips */ + +static void seq_count(ListBase *seqbase, int *tot) +{ + Sequence *seq; + + for(seq=seqbase->first; seq; seq=seq->next) { + (*tot)++; + + if(seq->seqbase.first) + seq_count(&seq->seqbase, tot); + } +} + +static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth) +{ + Sequence *seq; + + for(seq=seqbase->first; seq; seq=seq->next) { + seq->depth= depth; + + if(seq->seqbase.first) + seq_build_array(&seq->seqbase, array, depth+1); + + **array= seq; + (*array)++; + } +} + +void seq_array(Editing *ed, Sequence ***seqarray, int *tot, int use_pointer) +{ + Sequence **array; + + *seqarray= NULL; + *tot= 0; + + if(ed == NULL) + return; + + if(use_pointer) + seq_count(ed->seqbasep, tot); + else + seq_count(&ed->seqbase, tot); + + if(*tot == 0) + return; + + *seqarray= array= MEM_mallocN(sizeof(Sequence *)*(*tot), "SeqArray"); + if(use_pointer) + seq_build_array(ed->seqbasep, &array, 0); + else + seq_build_array(&ed->seqbase, &array, 0); +} + +void seq_begin(Editing *ed, SeqIterator *iter, int use_pointer) +{ + memset(iter, 0, sizeof(*iter)); + seq_array(ed, &iter->array, &iter->tot, use_pointer); + + if(iter->tot) { + iter->cur= 0; + iter->seq= iter->array[iter->cur]; + iter->valid= 1; + } +} + +void seq_next(SeqIterator *iter) +{ + if(++iter->cur < iter->tot) + iter->seq= iter->array[iter->cur]; + else + iter->valid= 0; +} + +void seq_end(SeqIterator *iter) +{ + if(iter->array) + MEM_freeN(iter->array); + + iter->valid= 0; +} + +/* + ********************************************************************** + * build_seqar + ********************************************************************** + * Build a complete array of _all_ sequencies (including those + * in metastrips!) + ********************************************************************** +*/ + +static void do_seq_count(ListBase *seqbase, int *totseq) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + (*totseq)++; + if(seq->seqbase.first) do_seq_count(&seq->seqbase, totseq); + seq= seq->next; + } +} + +static void do_build_seqar(ListBase *seqbase, Sequence ***seqar, int depth) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + seq->depth= depth; + if(seq->seqbase.first) do_build_seqar(&seq->seqbase, seqar, depth+1); + **seqar= seq; + (*seqar)++; + seq= seq->next; + } +} + +void build_seqar(ListBase *seqbase, Sequence ***seqar, int *totseq) +{ + Sequence **tseqar; + + *totseq= 0; + do_seq_count(seqbase, totseq); + + if(*totseq==0) { + *seqar= 0; + return; + } + *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); + tseqar= *seqar; + + do_build_seqar(seqbase, seqar, 0); + *seqar= tseqar; +} + +static void do_seq_count_cb(ListBase *seqbase, int *totseq, + int (*test_func)(Sequence * seq)) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + int test = test_func(seq); + if (test & BUILD_SEQAR_COUNT_CURRENT) { + (*totseq)++; + } + if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { + do_seq_count_cb(&seq->seqbase, totseq, test_func); + } + seq= seq->next; + } +} + +static void do_build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int depth, + int (*test_func)(Sequence * seq)) +{ + Sequence *seq; + + seq= seqbase->first; + while(seq) { + int test = test_func(seq); + seq->depth= depth; + + if(seq->seqbase.first && (test & BUILD_SEQAR_COUNT_CHILDREN)) { + do_build_seqar_cb(&seq->seqbase, seqar, depth+1, + test_func); + } + if (test & BUILD_SEQAR_COUNT_CURRENT) { + **seqar= seq; + (*seqar)++; + } + seq= seq->next; + } +} + +void build_seqar_cb(ListBase *seqbase, Sequence ***seqar, int *totseq, + int (*test_func)(Sequence * seq)) +{ + Sequence **tseqar; + + *totseq= 0; + do_seq_count_cb(seqbase, totseq, test_func); + + if(*totseq==0) { + *seqar= 0; + return; + } + *seqar= MEM_mallocN(sizeof(void *)* *totseq, "seqar"); + tseqar= *seqar; + + do_build_seqar_cb(seqbase, seqar, 0, test_func); + *seqar= tseqar; +} + + +void calc_sequence_disp(Sequence *seq) +{ + if(seq->startofs && seq->startstill) seq->startstill= 0; + if(seq->endofs && seq->endstill) seq->endstill= 0; + + seq->startdisp= seq->start + seq->startofs - seq->startstill; + seq->enddisp= seq->start+seq->len - seq->endofs + seq->endstill; + + seq->handsize= 10.0; /* 10 frames */ + if( seq->enddisp-seq->startdisp < 10 ) { + seq->handsize= (float)(0.5*(seq->enddisp-seq->startdisp)); + } + else if(seq->enddisp-seq->startdisp > 250) { + seq->handsize= (float)((seq->enddisp-seq->startdisp)/25); + } +} + +void calc_sequence(Sequence *seq) +{ + Sequence *seqm; + int min, max; + + /* check all metas recursively */ + seqm= seq->seqbase.first; + while(seqm) { + if(seqm->seqbase.first) calc_sequence(seqm); + seqm= seqm->next; + } + + /* effects and meta: automatic start and end */ + + if(seq->type & SEQ_EFFECT) { + /* pointers */ + if(seq->seq2==0) seq->seq2= seq->seq1; + if(seq->seq3==0) seq->seq3= seq->seq1; + + /* effecten go from seq1 -> seq2: test */ + + /* we take the largest start and smallest end */ + + // seq->start= seq->startdisp= MAX2(seq->seq1->startdisp, seq->seq2->startdisp); + // seq->enddisp= MIN2(seq->seq1->enddisp, seq->seq2->enddisp); + + if (seq->seq1) { + seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); + seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); + seq->len= seq->enddisp - seq->startdisp; + } else { + calc_sequence_disp(seq); + } + + if(seq->strip && seq->len!=seq->strip->len) { + new_tstripdata(seq); + } + + } + else { + if(seq->type==SEQ_META) { + seqm= seq->seqbase.first; + if(seqm) { + min= 1000000; + max= -1000000; + while(seqm) { + if(seqm->startdisp < min) min= seqm->startdisp; + if(seqm->enddisp > max) max= seqm->enddisp; + seqm= seqm->next; + } + seq->start= min + seq->anim_startofs; + seq->len = max-min; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + + if(seq->strip && seq->len!=seq->strip->len) { + new_tstripdata(seq); + } + } + } + calc_sequence_disp(seq); + } +} + +void reload_sequence_new_file(Scene *scene, Sequence * seq) +{ + char str[FILE_MAXDIR+FILE_MAXFILE]; + + if (!(seq->type == SEQ_MOVIE || seq->type == SEQ_IMAGE || + seq->type == SEQ_HD_SOUND || seq->type == SEQ_RAM_SOUND || + seq->type == SEQ_SCENE || seq->type == SEQ_META)) { + return; + } + + new_tstripdata(seq); + + if (seq->type != SEQ_SCENE && seq->type != SEQ_META && + seq->type != SEQ_IMAGE) { + BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name); + BLI_convertstringcode(str, G.sce); + BLI_convertstringframe(str, scene->r.cfra); + + } + + if (seq->type == SEQ_IMAGE) { + /* Hack? */ + int olen = MEM_allocN_len(seq->strip->stripdata)/sizeof(struct StripElem); + seq->len = olen; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_MOVIE) { + if(seq->anim) IMB_free_anim(seq->anim); + seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0)); + + if (!seq->anim) { + return; + } + + seq->len = IMB_anim_get_duration(seq->anim); + + seq->anim_preseek = IMB_anim_get_preseek(seq->anim); + + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_HD_SOUND) { +// XXX if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); +// seq->hdaudio = sound_open_hdaudio(str); + + if (!seq->hdaudio) { + return; + } + +// XXX seq->len = sound_hdaudio_get_duration(seq->hdaudio, FPS) - seq->anim_startofs - seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_RAM_SOUND) { + seq->len = (int) ( ((float)(seq->sound->streamlen-1)/ + ((float)scene->audio.mixrate*4.0 )) + * FPS); + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } else if (seq->type == SEQ_SCENE) { + Scene * sce = G.main->scene.first; + int nr = 1; + + while(sce) { + if(nr == seq->scenenr) { + break; + } + nr++; + sce= sce->id.next; + } + + if (sce) { + seq->scene = sce; + } else { + sce = seq->scene; + } + + strncpy(seq->name + 2, sce->id.name + 2, + sizeof(seq->name) - 2); + + seq->len= seq->scene->r.efra - seq->scene->r.sfra + 1; + seq->len -= seq->anim_startofs; + seq->len -= seq->anim_endofs; + if (seq->len < 0) { + seq->len = 0; + } + seq->strip->len = seq->len; + } + + free_proxy_seq(seq); + + calc_sequence(seq); +} + +void sort_seq(Scene *scene) +{ + /* all strips together per kind, and in order of y location ("machine") */ + ListBase seqbase, effbase; + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq, *seqt; + + + if(ed==NULL) return; + + seqbase.first= seqbase.last= 0; + effbase.first= effbase.last= 0; + + while( (seq= ed->seqbasep->first) ) { + BLI_remlink(ed->seqbasep, seq); + + if(seq->type & SEQ_EFFECT) { + seqt= effbase.first; + while(seqt) { + if(seqt->machine>=seq->machine) { + BLI_insertlinkbefore(&effbase, seqt, seq); + break; + } + seqt= seqt->next; + } + if(seqt==0) BLI_addtail(&effbase, seq); + } + else { + seqt= seqbase.first; + while(seqt) { + if(seqt->machine>=seq->machine) { + BLI_insertlinkbefore(&seqbase, seqt, seq); + break; + } + seqt= seqt->next; + } + if(seqt==0) BLI_addtail(&seqbase, seq); + } + } + + addlisttolist(&seqbase, &effbase); + *(ed->seqbasep)= seqbase; +} + + +void clear_scene_in_allseqs(Scene *sce) +{ + Scene *sce1; + Editing *ed; + Sequence *seq; + + /* when a scene is deleted: test all seqs */ + + sce1= G.main->scene.first; + while(sce1) { + if(sce1!=sce && sce1->ed) { + ed= sce1->ed; + + SEQ_BEGIN(ed, seq) { + + if(seq->scene==sce) seq->scene= 0; + + } + SEQ_END + } + + sce1= sce1->id.next; + } +} + +char *give_seqname_by_type(int type) +{ + switch(type) { + case SEQ_META: return "Meta"; + case SEQ_IMAGE: return "Image"; + case SEQ_SCENE: return "Scene"; + case SEQ_MOVIE: return "Movie"; + case SEQ_RAM_SOUND: return "Audio (RAM)"; + case SEQ_HD_SOUND: return "Audio (HD)"; + case SEQ_CROSS: return "Cross"; + case SEQ_GAMCROSS: return "Gamma Cross"; + case SEQ_ADD: return "Add"; + case SEQ_SUB: return "Sub"; + case SEQ_MUL: return "Mul"; + case SEQ_ALPHAOVER: return "Alpha Over"; + case SEQ_ALPHAUNDER: return "Alpha Under"; + case SEQ_OVERDROP: return "Over Drop"; + case SEQ_WIPE: return "Wipe"; + case SEQ_GLOW: return "Glow"; + case SEQ_TRANSFORM: return "Transform"; + case SEQ_COLOR: return "Color"; + case SEQ_SPEED: return "Speed"; + default: + return 0; + } +} + +char *give_seqname(Sequence *seq) +{ + char * name = give_seqname_by_type(seq->type); + + if (!name) { + if(seq->type<SEQ_EFFECT) { + return seq->strip->dir; + } else if(seq->type==SEQ_PLUGIN) { + if(!(seq->flag & SEQ_EFFECT_NOT_LOADED) && + seq->plugin && seq->plugin->doit) { + return seq->plugin->pname; + } else { + return "Plugin"; + } + } else { + return "Effect"; + } + } + return name; +} + +/* ***************** DO THE SEQUENCE ***************** */ + +static void make_black_ibuf(ImBuf *ibuf) +{ + unsigned int *rect; + float *rect_float; + int tot; + + if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; + + tot= ibuf->x*ibuf->y; + + rect= ibuf->rect; + rect_float = ibuf->rect_float; + + if (rect) { + memset(rect, 0, tot * sizeof(char) * 4); + } + + if (rect_float) { + memset(rect_float, 0, tot * sizeof(float) * 4); + } +} + +static void multibuf(ImBuf *ibuf, float fmul) +{ + char *rt; + float *rt_float; + + int a, mul, icol; + + mul= (int)(256.0*fmul); + rt= (char *)ibuf->rect; + rt_float = ibuf->rect_float; + + if (rt) { + a= ibuf->x*ibuf->y; + while(a--) { + + icol= (mul*rt[0])>>8; + if(icol>254) rt[0]= 255; else rt[0]= icol; + icol= (mul*rt[1])>>8; + if(icol>254) rt[1]= 255; else rt[1]= icol; + icol= (mul*rt[2])>>8; + if(icol>254) rt[2]= 255; else rt[2]= icol; + icol= (mul*rt[3])>>8; + if(icol>254) rt[3]= 255; else rt[3]= icol; + + rt+= 4; + } + } + if (rt_float) { + a= ibuf->x*ibuf->y; + while(a--) { + rt_float[0] *= fmul; + rt_float[1] *= fmul; + rt_float[2] *= fmul; + rt_float[3] *= fmul; + + rt_float += 4; + } + } +} + +static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se) +{ + TStripElem *se1, *se2, *se3; + float fac, facf; + int x, y; + int early_out; + struct SeqEffectHandle sh = get_sequence_effect(seq); + + if (!sh.execute) { /* effect not supported in this version... */ + make_black_ibuf(se->ibuf); + return; + } + +#if 0 // XXX old animation system + if(seq->ipo && seq->ipo->curve.first) { + do_seq_ipo(scene, seq, cfra); + fac= seq->facf0; + facf= seq->facf1; + } else +#endif // XXX old animation system + { + sh.get_default_fac(seq, cfra, &fac, &facf); + } + + if( !(scene->r.mode & R_FIELDS) ) facf = fac; + + early_out = sh.early_out(seq, fac, facf); + + if (early_out == -1) { /* no input needed */ + sh.execute(seq, cfra, fac, facf, + se->ibuf->x, se->ibuf->y, + 0, 0, 0, se->ibuf); + return; + } + + switch (early_out) { + case 0: + if (se->se1==0 || se->se2==0 || se->se3==0) { + make_black_ibuf(se->ibuf); + return; + } + + se1= se->se1; + se2= se->se2; + se3= se->se3; + + if ( (se1==0 || se2==0 || se3==0) + || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) { + make_black_ibuf(se->ibuf); + return; + } + + break; + case 1: + if (se->se1 == 0) { + make_black_ibuf(se->ibuf); + return; + } + + se1= se->se1; + + if (se1 == 0 || se1->ibuf == 0) { + make_black_ibuf(se->ibuf); + return; + } + + if (se->ibuf != se1->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se1->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + case 2: + if (se->se2 == 0) { + make_black_ibuf(se->ibuf); + return; + } + + se2= se->se2; + + if (se2 == 0 || se2->ibuf == 0) { + make_black_ibuf(se->ibuf); + return; + } + if (se->ibuf != se2->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se2->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + default: + make_black_ibuf(se->ibuf); + return; + } + + x= se2->ibuf->x; + y= se2->ibuf->y; + + if (!se1->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se1->ibuf); + } + if (!se2->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se2->ibuf); + } + if (!se3->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se3->ibuf); + } + + if (!se1->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se1->ibuf); + } + if (!se2->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se2->ibuf); + } + if (!se3->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se3->ibuf); + } + + sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, + se->ibuf); +} + +static int give_stripelem_index(Sequence *seq, int cfra) +{ + int nr; + + if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1; + if(seq->len == 0) return -1; + if(seq->flag&SEQ_REVERSE_FRAMES) { + /*reverse frame in this sequence */ + if(cfra <= seq->start) nr= seq->len-1; + else if(cfra >= seq->start+seq->len-1) nr= 0; + else nr= (seq->start + seq->len) - cfra; + } else { + if(cfra <= seq->start) nr= 0; + else if(cfra >= seq->start+seq->len-1) nr= seq->len-1; + else nr= cfra-seq->start; + } + if (seq->strobe < 1.0) seq->strobe = 1.0; + if (seq->strobe > 1.0) { + nr -= (int)fmod((double)nr, (double)seq->strobe); + } + + return nr; +} + +static TStripElem* alloc_tstripdata(int len, const char * name) +{ + int i; + TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name); + for (i = 0; i < len; i++) { + se[i].ok = STRIPELEM_OK; + } + return se; +} + +TStripElem *give_tstripelem(Sequence *seq, int cfra) +{ + TStripElem *se; + int nr; + + se = seq->strip->tstripdata; + if (se == 0 && seq->len > 0) { + se = seq->strip->tstripdata = alloc_tstripdata(seq->len, + "tstripelems"); + } + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; + + se += nr; + + /* if there are IPOs with blend modes active, one has to watch out + for startstill + endstill area: we can't use the same tstripelem + here for all ibufs, since then, blending with IPOs won't work! + + Rather common case, if you use a single image and try to fade + it in and out... or want to use your strip as a watermark in + alpha over mode... + */ + if (seq->blend_mode != SEQ_BLEND_REPLACE || + (/*seq->ipo && seq->ipo->curve.first &&*/ + (!(seq->type & SEQ_EFFECT) || !seq->seq1))) { + Strip * s = seq->strip; + if (cfra < seq->start) { + se = s->tstripdata_startstill; + if (seq->startstill > s->startstill) { + free_tstripdata(s->startstill, + s->tstripdata_startstill); + se = 0; + } + + if (se == 0) { + s->startstill = seq->startstill; + se = seq->strip->tstripdata_startstill + = alloc_tstripdata( + s->startstill, + "tstripelems_startstill"); + } + se += seq->start - cfra - 1; + + } else if (cfra > seq->start + seq->len-1) { + se = s->tstripdata_endstill; + if (seq->endstill > s->endstill) { + free_tstripdata(s->endstill, + s->tstripdata_endstill); + se = 0; + } + + if (se == 0) { + s->endstill = seq->endstill; + se = seq->strip->tstripdata_endstill + = alloc_tstripdata( + s->endstill, + "tstripelems_endstill"); + } + se += cfra - (seq->start + seq->len-1) - 1; + } + } + + + se->nr= nr; + + return se; +} + +StripElem *give_stripelem(Sequence *seq, int cfra) +{ + StripElem *se; + int nr; + + se = seq->strip->stripdata; + nr = give_stripelem_index(seq, cfra); + + if (nr == -1) return 0; + if (se == 0) return 0; + + se += nr + seq->anim_startofs; + + return se; +} + +static int evaluate_seq_frame_gen(Sequence ** seq_arr, ListBase *seqbase, int cfra) +{ + Sequence *seq; + int totseq=0; + + memset(seq_arr, 0, sizeof(Sequence*) * (MAXSEQ+1)); + + seq= seqbase->first; + while(seq) { + if(seq->startdisp <=cfra && seq->enddisp > cfra) { + seq_arr[seq->machine]= seq; + totseq++; + } + seq= seq->next; + } + + return totseq; +} + +int evaluate_seq_frame(Scene *scene, int cfra) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq_arr[MAXSEQ+1]; + + if(ed==NULL) return 0; + return evaluate_seq_frame_gen(seq_arr, ed->seqbasep, cfra); +} + +static int video_seq_is_rendered(Sequence * seq) +{ + return (seq + && !(seq->flag & SEQ_MUTE) + && seq->type != SEQ_RAM_SOUND + && seq->type != SEQ_HD_SOUND); +} + +static int get_shown_sequences( ListBase * seqbasep, int cfra, int chanshown, Sequence ** seq_arr_out) +{ + Sequence *seq_arr[MAXSEQ+1]; + int b = chanshown; + int cnt = 0; + + if (b > MAXSEQ) { + return 0; + } + + if(evaluate_seq_frame_gen(seq_arr, seqbasep, cfra)) { + if (b > 0) { + if (seq_arr[b] == 0) { + return 0; + } + } else { + for (b = MAXSEQ; b > 0; b--) { + if (video_seq_is_rendered(seq_arr[b])) { + break; + } + } + } + } + + chanshown = b; + + for (;b > 0; b--) { + if (video_seq_is_rendered(seq_arr[b])) { + if (seq_arr[b]->blend_mode == SEQ_BLEND_REPLACE) { + break; + } + } + } + + for (;b <= chanshown; b++) { + if (video_seq_is_rendered(seq_arr[b])) { + seq_arr_out[cnt++] = seq_arr[b]; + } + } + + return cnt; +} + + +/* ********************************************************************** + proxy management + ********************************************************************** */ + +#define PROXY_MAXFILE (2*FILE_MAXDIR+FILE_MAXFILE) + +static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * name, int render_size) +{ + int frameno; + char dir[FILE_MAXDIR]; + + if (!seq->strip->proxy) { + return FALSE; + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_DIR) { + strcpy(dir, seq->strip->proxy->dir); + } else { + if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) { + snprintf(dir, FILE_MAXDIR, "%s/BL_proxy", + seq->strip->dir); + } else { + return FALSE; + } + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + BLI_join_dirfile(name, dir, seq->strip->proxy->file); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, cfra); + + return TRUE; + } + + /* generate a seperate proxy directory for each preview size */ + + if (seq->type == SEQ_IMAGE) { + StripElem * se = give_stripelem(seq, cfra); + snprintf(name, PROXY_MAXFILE, "%s/images/%d/%s_proxy", + dir, render_size, se->name); + frameno = 1; + } else if (seq->type == SEQ_MOVIE) { + TStripElem * tse = give_tstripelem(seq, cfra); + + frameno = tse->nr + seq->anim_startofs; + + snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir, + seq->strip->stripdata->name, + render_size); + } else { + TStripElem * tse = give_tstripelem(seq, cfra); + + frameno = tse->nr + seq->anim_startofs; + + snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir, + render_size); + } + + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, frameno); + + + strcat(name, ".jpg"); + + return TRUE; +} + +static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + char name[PROXY_MAXFILE]; + + if (!(seq->flag & SEQ_USE_PROXY)) { + return 0; + } + + /* rendering at 100% ? No real sense in proxy-ing, right? */ + if (render_size == 100) { + return 0; + } + + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + TStripElem * tse = give_tstripelem(seq, cfra); + int frameno = tse->nr + seq->anim_startofs; + if (!seq->strip->proxy->anim) { + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return 0; + } + + seq->strip->proxy->anim = openanim(name, IB_rect); + } + if (!seq->strip->proxy->anim) { + return 0; + } + + return IMB_anim_absolute(seq->strip->proxy->anim, frameno); + } + + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return 0; + } + + if (BLI_exists(name)) { + return IMB_loadiffname(name, IB_rect); + } else { + return 0; + } +} + +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, + int build_proxy_run, int render_size); + +static void seq_proxy_build_frame(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + char name[PROXY_MAXFILE]; + int quality; + TStripElem * se; + int ok; + int rectx, recty; + struct ImBuf * ibuf; + + if (!(seq->flag & SEQ_USE_PROXY)) { + return; + } + + /* rendering at 100% ? No real sense in proxy-ing, right? */ + if (render_size == 100) { + return; + } + + /* that's why it is called custom... */ + if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) { + return; + } + + if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) { + return; + } + + se = give_tstripelem(seq, cfra); + if (!se) { + return; + } + + if(se->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = 0; + } + + do_build_seq_ibuf(scene, seq, se, cfra, TRUE, render_size); + + if (!se->ibuf) { + return; + } + + rectx= (render_size*scene->r.xsch)/100; + recty= (render_size*scene->r.ysch)/100; + + ibuf = se->ibuf; + + if (ibuf->x != rectx || ibuf->y != recty) { + IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); + } + + /* quality is fixed, otherwise one has to generate seperate + directories for every quality... + + depth = 32 is intentionally left in, otherwise ALPHA channels + won't work... */ + quality = 90; + ibuf->ftype= JPG | quality; + + BLI_make_existing_file(name); + + ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat); + if (ok == 0) { + perror(name); + } + + IMB_freeImBuf(ibuf); + se->ibuf = 0; +} + +void seq_proxy_rebuild(Scene *scene, Sequence * seq) +{ + int cfra; + + waitcursor(1); + + G.afbreek = 0; + + /* flag management tries to account for strobe and + other "non-linearities", that might come in the future... + better way would be to "touch" the files, so that _really_ + no one is rebuild twice. + */ + + for (cfra = seq->startdisp; cfra < seq->enddisp; cfra++) { + TStripElem * tse = give_tstripelem(seq, cfra); + + tse->flag &= ~STRIPELEM_PREVIEW_DONE; + } + + /* a _lot_ faster for movie files, if we read frames in + sequential order */ + if (seq->flag & SEQ_REVERSE_FRAMES) { + for (cfra = seq->enddisp-seq->endstill-1; + cfra >= seq->startdisp + seq->startstill; cfra--) { + TStripElem * tse = give_tstripelem(seq, cfra); + + if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { + seq_proxy_build_frame(scene, seq, cfra, scene->r.size); + tse->flag |= STRIPELEM_PREVIEW_DONE; + } + if (blender_test_break()) { + break; + } + } + } else { + for (cfra = seq->startdisp + seq->startstill; + cfra < seq->enddisp - seq->endstill; cfra++) { + TStripElem * tse = give_tstripelem(seq, cfra); + + if (!(tse->flag & STRIPELEM_PREVIEW_DONE)) { + seq_proxy_build_frame(scene, seq, cfra, scene->r.size); + tse->flag |= STRIPELEM_PREVIEW_DONE; + } + if (blender_test_break()) { + break; + } + } + } + waitcursor(0); +} + + +/* ********************************************************************** + color balance + ********************************************************************** */ + +static StripColorBalance calc_cb(StripColorBalance * cb_) +{ + StripColorBalance cb = *cb_; + int c; + + if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_LIFT) { + for (c = 0; c < 3; c++) { + cb.lift[c] = 1.0 - cb.lift[c]; + } + } else { + for (c = 0; c < 3; c++) { + cb.lift[c] = -(1.0 - cb.lift[c]); + } + } + if (cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAIN) { + for (c = 0; c < 3; c++) { + if (cb.gain[c] != 0.0) { + cb.gain[c] = 1.0/cb.gain[c]; + } else { + cb.gain[c] = 1000000; /* should be enough :) */ + } + } + } + + if (!(cb.flag & SEQ_COLOR_BALANCE_INVERSE_GAMMA)) { + for (c = 0; c < 3; c++) { + if (cb.gamma[c] != 0.0) { + cb.gamma[c] = 1.0/cb.gamma[c]; + } else { + cb.gamma[c] = 1000000; /* should be enough :) */ + } + } + } + + return cb; +} + +static void make_cb_table_byte(float lift, float gain, float gamma, + unsigned char * table, float mul) +{ + int y; + + for (y = 0; y < 256; y++) { + float v = 1.0 * y / 255; + v *= gain; + v += lift; + v = pow(v, gamma); + v *= mul; + if ( v > 1.0) { + v = 1.0; + } else if (v < 0.0) { + v = 0.0; + } + table[y] = v * 255; + } + +} + +static void make_cb_table_float(float lift, float gain, float gamma, + float * table, float mul) +{ + int y; + + for (y = 0; y < 256; y++) { + float v = (float) y * 1.0 / 255.0; + v *= gain; + v += lift; + v = pow(v, gamma); + v *= mul; + table[y] = v; + } +} + +static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul) +{ + unsigned char cb_tab[3][256]; + int c; + unsigned char * p = (unsigned char*) se->ibuf->rect; + unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + + StripColorBalance cb = calc_cb(seq->strip->color_balance); + + for (c = 0; c < 3; c++) { + make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], + cb_tab[c], mul); + } + + while (p < e) { + p[0] = cb_tab[0][p[0]]; + p[1] = cb_tab[1][p[1]]; + p[2] = cb_tab[2][p[2]]; + + p += 4; + } +} + +static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul) +{ + float cb_tab[4][256]; + int c,i; + unsigned char * p = (unsigned char*) se->ibuf->rect; + unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y; + float * o; + StripColorBalance cb; + + imb_addrectfloatImBuf(se->ibuf); + + o = se->ibuf->rect_float; + + cb = calc_cb(seq->strip->color_balance); + + for (c = 0; c < 3; c++) { + make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], + cb_tab[c], mul); + } + + for (i = 0; i < 256; i++) { + cb_tab[3][i] = ((float)i)*(1.0f/255.0f); + } + + while (p < e) { + o[0] = cb_tab[0][p[0]]; + o[1] = cb_tab[1][p[1]]; + o[2] = cb_tab[2][p[2]]; + o[3] = cb_tab[3][p[3]]; + + p += 4; o += 4; + } +} + +static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul) +{ + float * p = se->ibuf->rect_float; + float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y; + StripColorBalance cb = calc_cb(seq->strip->color_balance); + + while (p < e) { + int c; + for (c = 0; c < 3; c++) { + p[c] = pow(p[c] * cb.gain[c] + cb.lift[c], + cb.gamma[c]) * mul; + } + p += 4; + } +} + +static void color_balance(Sequence * seq, TStripElem* se, float mul) +{ + if (se->ibuf->rect_float) { + color_balance_float_float(seq, se, mul); + } else if(seq->flag & SEQ_MAKE_FLOAT) { + color_balance_byte_float(seq, se, mul); + } else { + color_balance_byte_byte(seq, se, mul); + } +} + +/* + input preprocessing for SEQ_IMAGE, SEQ_MOVIE and SEQ_SCENE + + Do all the things you can't really do afterwards using sequence effects + (read: before rescaling to render resolution has been done) + + Order is important! + + - Deinterlace + - Crop and transform in image source coordinate space + - Flip X + Flip Y (could be done afterwards, backward compatibility) + - Promote image to float data (affects pipeline operations afterwards) + - Color balance (is most efficient in the byte -> float + (future: half -> float should also work fine!) + case, if done on load, since we can use lookup tables) + - Premultiply + +*/ + +static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra) +{ + float mul; + + if ((seq->flag & SEQ_FILTERY) || + (seq->flag & SEQ_USE_CROP) || + (seq->flag & SEQ_USE_TRANSFORM) || + (seq->flag & SEQ_FLIPX) || + (seq->flag & SEQ_FLIPY) || + (seq->flag & SEQ_USE_COLOR_BALANCE) || + (seq->flag & SEQ_MAKE_PREMUL) || + (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) { + return TRUE; + } + + mul = seq->mul; + + if(seq->blend_mode == SEQ_BLEND_REPLACE) { +#if 0 // XXX old animation system + if (seq->ipo && seq->ipo->curve.first) { + do_seq_ipo(scene, seq, cfra); + mul *= seq->facf0; + } +#endif // XXX old animation system + mul *= seq->blend_opacity / 100.0; + } + + if (mul != 1.0) { + return TRUE; + } + + return FALSE; +} + +static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra) +{ + float mul; + + seq->strip->orx= se->ibuf->x; + seq->strip->ory= se->ibuf->y; + + if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) { + IMB_filtery(se->ibuf); + } + + if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) { + StripCrop c; + StripTransform t; + int sx,sy,dx,dy; + + memset(&c, 0, sizeof(StripCrop)); + memset(&t, 0, sizeof(StripTransform)); + + if(seq->flag & SEQ_USE_CROP && seq->strip->crop) { + c = *seq->strip->crop; + } + if(seq->flag & SEQ_USE_TRANSFORM && seq->strip->transform) { + t = *seq->strip->transform; + } + + sx = se->ibuf->x - c.left - c.right; + sy = se->ibuf->y - c.top - c.bottom; + dx = sx; + dy = sy; + + if (seq->flag & SEQ_USE_TRANSFORM) { + dx = scene->r.xsch; + dy = scene->r.ysch; + } + + if (c.top + c.bottom >= se->ibuf->y || + c.left + c.right >= se->ibuf->x || + t.xofs >= dx || t.yofs >= dy) { + make_black_ibuf(se->ibuf); + } else { + ImBuf * i; + + if (se->ibuf->rect_float) { + i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0); + } else { + i = IMB_allocImBuf(dx, dy,32, IB_rect, 0); + } + + IMB_rectcpy(i, se->ibuf, + t.xofs, t.yofs, + c.left, c.bottom, + sx, sy); + + IMB_freeImBuf(se->ibuf); + + se->ibuf = i; + } + } + + if(seq->flag & SEQ_FLIPX) { + IMB_flipx(se->ibuf); + } + if(seq->flag & SEQ_FLIPY) { + IMB_flipy(se->ibuf); + } + + if(seq->mul == 0.0) { + seq->mul = 1.0; + } + + mul = seq->mul; + + if(seq->blend_mode == SEQ_BLEND_REPLACE) { +#if 0 // XXX old animation system + if (seq->ipo && seq->ipo->curve.first) { + do_seq_ipo(scene, seq, cfra); + mul *= seq->facf0; + } +#endif // XXX old animation system + mul *= seq->blend_opacity / 100.0; + } + + if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) { + color_balance(seq, se, mul); + mul = 1.0; + } + + if(seq->flag & SEQ_MAKE_FLOAT) { + if (!se->ibuf->rect_float) { + IMB_float_from_rect(se->ibuf); + } + if (se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + } + + if(mul != 1.0) { + multibuf(se->ibuf, mul); + } + + if(seq->flag & SEQ_MAKE_PREMUL) { + if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) { + converttopremul(se->ibuf); + } + } + + + if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) { + if(scene->r.mode & R_OSA) { + IMB_scaleImBuf(se->ibuf, + (short)seqrectx, (short)seqrecty); + } else { + IMB_scalefastImBuf(se->ibuf, + (short)seqrectx, (short)seqrecty); + } + } +} + +/* test if image too small or discarded from cache: reload */ + +static void test_and_auto_discard_ibuf(TStripElem * se) +{ + if (se->ibuf) { + if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty + || !(se->ibuf->rect || se->ibuf->rect_float)) { + IMB_freeImBuf(se->ibuf); + + se->ibuf= 0; + se->ok= STRIPELEM_OK; + } + } + if (se->ibuf_comp) { + if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty + || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) { + IMB_freeImBuf(se->ibuf_comp); + + se->ibuf_comp = 0; + } + } +} + +static void test_and_auto_discard_ibuf_stills(Strip * strip) +{ + if (strip->ibuf_startstill) { + if (!strip->ibuf_startstill->rect && + !strip->ibuf_startstill->rect_float) { + IMB_freeImBuf(strip->ibuf_startstill); + strip->ibuf_startstill = 0; + } + } + if (strip->ibuf_endstill) { + if (!strip->ibuf_endstill->rect && + !strip->ibuf_endstill->rect_float) { + IMB_freeImBuf(strip->ibuf_endstill); + strip->ibuf_endstill = 0; + } + } +} + +static void copy_from_ibuf_still(Sequence * seq, TStripElem * se) +{ + if (!se->ibuf) { + if (se->nr == 0 && seq->strip->ibuf_startstill) { + IMB_cache_limiter_touch(seq->strip->ibuf_startstill); + + se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill); + } + if (se->nr == seq->len - 1 + && (seq->len != 1) + && seq->strip->ibuf_endstill) { + IMB_cache_limiter_touch(seq->strip->ibuf_endstill); + + se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill); + } + } +} + +static void copy_to_ibuf_still(Sequence * seq, TStripElem * se) +{ + if (se->ibuf) { + if (se->nr == 0) { + seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_insert(seq->strip->ibuf_startstill); + IMB_cache_limiter_touch(seq->strip->ibuf_startstill); + } + if (se->nr == seq->len - 1 && seq->len != 1) { + seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_insert(seq->strip->ibuf_endstill); + IMB_cache_limiter_touch(seq->strip->ibuf_endstill); + } + } +} + +static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown) +{ + Sequence* seq_arr[MAXSEQ+1]; + int i; + TStripElem* se = 0; + + evaluate_seq_frame_gen(seq_arr, seqbasep, cfra); + + for (i = 0; i < MAXSEQ; i++) { + if (!video_seq_is_rendered(seq_arr[i])) { + continue; + } + se = give_tstripelem(seq_arr[i], cfra); + if (se) { + if (se->ibuf) { + IMB_freeImBuf(se->ibuf); + + se->ibuf= 0; + se->ok= STRIPELEM_OK; + } + + if (se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + + se->ibuf_comp = 0; + } + } + } + +} + +static void check_limiter_refcount(const char * func, TStripElem *se) +{ + if (se && se->ibuf) { + int refcount = IMB_cache_limiter_get_refcount(se->ibuf); + if (refcount != 1) { + /* can happen on complex pipelines */ + if (refcount > 1 && (G.f & G_DEBUG) == 0) { + return; + } + + fprintf(stderr, + "sequencer: (ibuf) %s: " + "suspicious memcache " + "limiter refcount: %d\n", func, refcount); + } + } +} + +static void check_limiter_refcount_comp(const char * func, TStripElem *se) +{ + if (se && se->ibuf_comp) { + int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp); + if (refcount != 1) { + /* can happen on complex pipelines */ + if (refcount > 1 && (G.f & G_DEBUG) == 0) { + return; + } + fprintf(stderr, + "sequencer: (ibuf comp) %s: " + "suspicious memcache " + "limiter refcount: %d\n", func, refcount); + } + } +} + +static TStripElem* do_build_seq_array_recursively(Scene *scene, + ListBase *seqbasep, int cfra, int chanshown, int render_size); + +static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra, + int build_proxy_run, int render_size) +{ + char name[FILE_MAXDIR+FILE_MAXFILE]; + int use_limiter = TRUE; + + test_and_auto_discard_ibuf(se); + test_and_auto_discard_ibuf_stills(seq->strip); + + if(seq->type == SEQ_META) { + TStripElem * meta_se = 0; + int use_preprocess = FALSE; + use_limiter = FALSE; + + if (!build_proxy_run && se->ibuf == 0) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + if (se->ibuf) { + use_limiter = TRUE; + use_preprocess = TRUE; + } + } + + if(!se->ibuf && seq->seqbase.first) { + meta_se = do_build_seq_array_recursively(scene, + &seq->seqbase, seq->start + se->nr, 0, + render_size); + + check_limiter_refcount("do_build_seq_ibuf: for META", meta_se); + } + + se->ok = STRIPELEM_OK; + + if(!se->ibuf && meta_se) { + se->ibuf = meta_se->ibuf_comp; + if(se->ibuf && + (!input_have_to_preprocess(scene, seq, se, cfra) || + build_proxy_run)) { + IMB_refImBuf(se->ibuf); + if (build_proxy_run) { + IMB_cache_limiter_unref(se->ibuf); + } + } else if (se->ibuf) { + struct ImBuf * i = IMB_dupImBuf(se->ibuf); + + IMB_cache_limiter_unref(se->ibuf); + + se->ibuf = i; + + use_limiter = TRUE; + use_preprocess = TRUE; + } + } else if (se->ibuf) { + use_limiter = TRUE; + } + if (meta_se) { + free_metastrip_imbufs( + &seq->seqbase, seq->start + se->nr, 0); + } + + if (use_preprocess) { + input_preprocess(scene, seq, se, cfra); + } + } else if(seq->type & SEQ_EFFECT) { + /* should the effect be recalculated? */ + + if (!build_proxy_run && se->ibuf == 0) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + + if(se->ibuf == 0) { + /* if any inputs are rectfloat, output is float too */ + if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) || + (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) || + (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + do_effect(scene, cfra, seq, se); + } + } else if(seq->type == SEQ_IMAGE) { + if(se->ok == STRIPELEM_OK && se->ibuf == 0) { + StripElem * s_elem = give_stripelem(seq, cfra); + BLI_join_dirfile(name, seq->strip->dir, s_elem->name); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, scene->r.cfra); + if (!build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + copy_from_ibuf_still(seq, se); + + if (!se->ibuf) { + se->ibuf= IMB_loadiffname( + name, IB_rect); + /* we don't need both (speed reasons)! */ + if (se->ibuf && + se->ibuf->rect_float && se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + + copy_to_ibuf_still(seq, se); + } + + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else if (!build_proxy_run) { + input_preprocess(scene, seq, se, cfra); + } + } + } else if(seq->type == SEQ_MOVIE) { + if(se->ok == STRIPELEM_OK && se->ibuf==0) { + if(!build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + } + copy_from_ibuf_still(seq, se); + + if (se->ibuf == 0) { + if(seq->anim==0) { + BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name); + BLI_convertstringcode(name, G.sce); + BLI_convertstringframe(name, scene->r.cfra); + + seq->anim = openanim( + name, IB_rect | + ((seq->flag & SEQ_FILTERY) + ? IB_animdeinterlace : 0)); + } + if(seq->anim) { + IMB_anim_set_preseek(seq->anim, seq->anim_preseek); + se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs); + /* we don't need both (speed reasons)! */ + if (se->ibuf + && se->ibuf->rect_float + && se->ibuf->rect) { + imb_freerectImBuf(se->ibuf); + } + + } + copy_to_ibuf_still(seq, se); + } + + if(se->ibuf == 0) { + se->ok = STRIPELEM_FAILED; + } else if (!build_proxy_run) { + input_preprocess(scene, seq, se, cfra); + } + } + } else if(seq->type == SEQ_SCENE) { // scene can be NULL after deletions +#if 0 + /* XXX move entirely to render? */ + int oldcfra = CFRA; + Sequence * oldseq = get_last_seq(); + Scene *sce= seq->scene, *oldsce= scene; + Render *re; + RenderResult rres; + int doseq, rendering= G.rendering; + char scenename[64]; + int sce_valid =sce&& (sce->camera || sce->r.scemode & R_DOSEQ); + + if (se->ibuf == NULL && sce_valid && !build_proxy_run) { + se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size); + if (se->ibuf) { + input_preprocess(scene, seq, se, cfra); + } + } + + if (se->ibuf == NULL && sce_valid) { + copy_from_ibuf_still(seq, se); + if (se->ibuf) { + input_preprocess(scene, seq, se, cfra); + } + } + + if (!sce_valid) { + se->ok = STRIPELEM_FAILED; + } else if (se->ibuf==NULL && sce_valid) { + /* no need to display a waitcursor on sequencer + scene strips */ + if (!(sce->r.scemode & R_DOSEQ)) + waitcursor(1); + + /* Hack! This function can be called from do_render_seq(), in that case + the seq->scene can already have a Render initialized with same name, + so we have to use a default name. (compositor uses scene name to + find render). + However, when called from within the UI (image preview in sequencer) + we do want to use scene Render, that way the render result is defined + for display in render/imagewindow */ + if(rendering) { + BLI_strncpy(scenename, sce->id.name+2, 64); + strcpy(sce->id.name+2, " do_build_seq_ibuf"); + } + re= RE_NewRender(sce->id.name); + + /* prevent eternal loop */ + doseq= scene->r.scemode & R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; + + BIF_init_render_callbacks(re, 0); /* 0= no display callbacks */ + + /* XXX hrms, set_scene still needed? work on that... */ + if(sce!=oldsce) set_scene_bg(sce); + RE_BlenderFrame(re, sce, + seq->sfra+se->nr+seq->anim_startofs); + if(sce!=oldsce) set_scene_bg(oldsce); + + /* UGLY WARNING, it is set to zero in RE_BlenderFrame */ + G.rendering= rendering; + if(rendering) + BLI_strncpy(sce->id.name+2, scenename, 64); + + RE_GetResultImage(re, &rres); + + if(rres.rectf) { + se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0); + memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty); + if(rres.rectz) { + addzbuffloatImBuf(se->ibuf); + memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty); + } + } else if (rres.rect32) { + se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0); + memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty); + } + + BIF_end_render_callbacks(); + + /* restore */ + scene->r.scemode |= doseq; + + // XXX +#if 0 + if((G.f & G_PLAYANIM)==0 /* bad, is set on do_render_seq */ + && !(sce->r.scemode & R_DOSEQ)) + waitcursor(0); +#endif + + CFRA = oldcfra; + set_last_seq(oldseq); + + copy_to_ibuf_still(seq, se); + + if (!build_proxy_run) { + if(se->ibuf == NULL) { + se->ok = STRIPELEM_FAILED; + } else { + input_preprocess(scene, seq, se, cfra); + } + } + + } +#endif + } + if (!build_proxy_run) { + if (se->ibuf && use_limiter) { + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + } +} + +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size); + +static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size) +{ + float fac, facf; + struct SeqEffectHandle sh = get_sequence_effect(seq); + int early_out; + + se->se1 = 0; + se->se2 = 0; + se->se3 = 0; + +#if 0 // XXX old animation system + if(seq->ipo && seq->ipo->curve.first) { + do_seq_ipo(scene, seq, cfra); + fac= seq->facf0; + facf= seq->facf1; + } else +#endif // XXX old animation system + { + sh.get_default_fac(seq, cfra, &fac, &facf); + } + + if( scene->r.mode & R_FIELDS ); else facf= fac; + + early_out = sh.early_out(seq, fac, facf); + switch (early_out) { + case -1: + /* no input needed */ + break; + case 0: + se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); + se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); + if (seq->seq3) { + se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size); + } + break; + case 1: + se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size); + break; + case 2: + se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size); + break; + } + + + do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + + /* children are not needed anymore ... */ + + if (se->se1 && se->se1->ibuf) { + IMB_cache_limiter_unref(se->se1->ibuf); + } + if (se->se2 && se->se2->ibuf) { + IMB_cache_limiter_unref(se->se2->ibuf); + } + if (se->se3 && se->se3->ibuf) { + IMB_cache_limiter_unref(se->se3->ibuf); + } + check_limiter_refcount("do_effect_seq_recursively", se); +} + +static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + TStripElem *se; + + se = give_tstripelem(seq, cfra); + + if(se) { + if (seq->type & SEQ_EFFECT) { + do_effect_seq_recursively(scene, seq, se, cfra, render_size); + } else { + do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size); + } + } + return se; +} + +/* FIXME: + +If cfra was float throughout blender (especially in the render +pipeline) one could even _render_ with subframe precision +instead of faking using the blend code below... + +*/ + +static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + SpeedControlVars * s = (SpeedControlVars *)seq->effectdata; + int nr = cfra - seq->start; + float f_cfra; + int cfra_left; + int cfra_right; + TStripElem * se = 0; + TStripElem * se1 = 0; + TStripElem * se2 = 0; + + sequence_effect_speed_rebuild_map(seq, 0); + + f_cfra = seq->start + s->frameMap[nr]; + + cfra_left = (int) floor(f_cfra); + cfra_right = (int) ceil(f_cfra); + + se = give_tstripelem(seq, cfra); + + if (!se) { + return se; + } + + if (cfra_left == cfra_right || + (s->flags & SEQ_SPEED_BLEND) == 0) { + test_and_auto_discard_ibuf(se); + + if (se->ibuf == NULL) { + se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); + + if((se1 && se1->ibuf && se1->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + if (se1 == 0 || se1->ibuf == 0) { + make_black_ibuf(se->ibuf); + } else { + if (se->ibuf != se1->ibuf) { + if (se->ibuf) { + IMB_freeImBuf(se->ibuf); + } + + se->ibuf = se1->ibuf; + IMB_refImBuf(se->ibuf); + } + } + } + } else { + struct SeqEffectHandle sh; + + if(se->ibuf) { + if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty + || !(se->ibuf->rect || se->ibuf->rect_float)) { + IMB_freeImBuf(se->ibuf); + se->ibuf= 0; + } + } + + if (se->ibuf == NULL) { + se1 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_left, render_size); + se2 = do_build_seq_recursively_impl(scene, seq->seq1, cfra_right, render_size); + + if((se1 && se1->ibuf && se1->ibuf->rect_float)) + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0); + else + se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0); + + if (!se1 || !se2) { + make_black_ibuf(se->ibuf); + } else { + sh = get_sequence_effect(seq); + + sh.execute(seq, cfra, + f_cfra - (float) cfra_left, + f_cfra - (float) cfra_left, + se->ibuf->x, se->ibuf->y, + se1->ibuf, se2->ibuf, 0, se->ibuf); + } + } + + } + + /* caller expects this to be referenced, so do it! */ + if (se->ibuf) { + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + + /* children are no longer needed */ + if (se1 && se1->ibuf) + IMB_cache_limiter_unref(se1->ibuf); + if (se2 && se2->ibuf) + IMB_cache_limiter_unref(se2->ibuf); + + check_limiter_refcount("do_handle_speed_effect", se); + + return se; +} + +/* + * build all ibufs recursively + * + * if successfull, the returned TStripElem contains the (referenced!) imbuf + * that means: you _must_ call + * + * IMB_cache_limiter_unref(rval); + * + * if rval != 0 + * + */ + +static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size) +{ + TStripElem *se; + if (seq->type == SEQ_SPEED) { + se = do_handle_speed_effect(scene, seq, cfra, render_size); + } else { + se = do_build_seq_recursively_impl(scene, seq, cfra, render_size); + } + + check_limiter_refcount("do_build_seq_recursively", se); + + return se; +} + +static TStripElem* do_build_seq_array_recursively(Scene *scene, + ListBase *seqbasep, int cfra, int chanshown, int render_size) +{ + Sequence* seq_arr[MAXSEQ+1]; + int count; + int i; + TStripElem* se = 0; + + count = get_shown_sequences(seqbasep, cfra, chanshown, (Sequence **)&seq_arr); + + if (!count) { + return 0; + } + + se = give_tstripelem(seq_arr[count - 1], cfra); + + if (!se) { + return 0; + } + + test_and_auto_discard_ibuf(se); + + if (se->ibuf_comp != 0) { + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + return se; + } + + + if(count == 1) { + se = do_build_seq_recursively(scene, seq_arr[0], cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } + return se; + } + + + for (i = count - 1; i >= 0; i--) { + int early_out; + Sequence * seq = seq_arr[i]; + struct SeqEffectHandle sh; + + se = give_tstripelem(seq, cfra); + + test_and_auto_discard_ibuf(se); + + if (se->ibuf_comp != 0) { + break; + } + if (seq->blend_mode == SEQ_BLEND_REPLACE) { + do_build_seq_recursively(scene, seq, cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf); + } else { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + } + + sh = get_sequence_blend(seq); + + seq->facf0 = seq->facf1 = 1.0; + +#if 0 // XXX old animation system + if(seq->ipo && seq->ipo->curve.first) { + do_seq_ipo(scene, seq, cfra); + } +#endif + + if( scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1; + + seq->facf0 *= seq->blend_opacity / 100.0; + seq->facf1 *= seq->blend_opacity / 100.0; + + early_out = sh.early_out(seq, seq->facf0, seq->facf1); + + switch (early_out) { + case -1: + case 2: + do_build_seq_recursively(scene, seq, cfra, render_size); + if (se->ibuf) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } else { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + case 1: + if (i == 0) { + se->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf_comp); + IMB_cache_limiter_ref(se->ibuf_comp); + IMB_cache_limiter_touch(se->ibuf_comp); + } + break; + case 0: + do_build_seq_recursively(scene, seq, cfra, render_size); + if (!se->ibuf) { + se->ibuf = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + IMB_cache_limiter_insert(se->ibuf); + IMB_cache_limiter_ref(se->ibuf); + IMB_cache_limiter_touch(se->ibuf); + } + if (i == 0) { + se->ibuf_comp = se->ibuf; + IMB_refImBuf(se->ibuf_comp); + } + break; + } + + if (se->ibuf_comp) { + break; + } + } + + i++; + + for (; i < count; i++) { + Sequence * seq = seq_arr[i]; + struct SeqEffectHandle sh = get_sequence_blend(seq); + TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra); + TStripElem* se2 = give_tstripelem(seq_arr[i], cfra); + + int early_out = sh.early_out(seq, seq->facf0, seq->facf1); + switch (early_out) { + case 0: { + int x= se2->ibuf->x; + int y= se2->ibuf->y; + int swap_input = FALSE; + + if (se1->ibuf_comp->rect_float || + se2->ibuf->rect_float) { + se2->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rectfloat, 0); + } else { + se2->ibuf_comp = IMB_allocImBuf( + (short)seqrectx, (short)seqrecty, + 32, IB_rect, 0); + } + + + if (!se1->ibuf_comp->rect_float && + se2->ibuf_comp->rect_float) { + IMB_float_from_rect(se1->ibuf_comp); + } + if (!se2->ibuf->rect_float && + se2->ibuf_comp->rect_float) { + IMB_float_from_rect(se2->ibuf); + } + + if (!se1->ibuf_comp->rect && + !se2->ibuf_comp->rect_float) { + IMB_rect_from_float(se1->ibuf_comp); + } + if (!se2->ibuf->rect && + !se2->ibuf_comp->rect_float) { + IMB_rect_from_float(se2->ibuf); + } + + /* bad hack, to fix crazy input ordering of + those two effects */ + + if (seq->blend_mode == SEQ_ALPHAOVER || + seq->blend_mode == SEQ_ALPHAUNDER || + seq->blend_mode == SEQ_OVERDROP) { + swap_input = TRUE; + } + + if (swap_input) { + sh.execute(seq, cfra, + seq->facf0, seq->facf1, x, y, + se2->ibuf, se1->ibuf_comp, 0, + se2->ibuf_comp); + } else { + sh.execute(seq, cfra, + seq->facf0, seq->facf1, x, y, + se1->ibuf_comp, se2->ibuf, 0, + se2->ibuf_comp); + } + + IMB_cache_limiter_insert(se2->ibuf_comp); + IMB_cache_limiter_ref(se2->ibuf_comp); + IMB_cache_limiter_touch(se2->ibuf_comp); + + IMB_cache_limiter_unref(se1->ibuf_comp); + IMB_cache_limiter_unref(se2->ibuf); + + break; + } + case 1: { + se2->ibuf_comp = se1->ibuf; + IMB_refImBuf(se2->ibuf_comp); + + break; + } + } + se = se2; + } + + return se; +} + +/* + * returned ImBuf is refed! + * you have to unref after usage! + */ + +static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + Editing *ed= seq_give_editing(scene, FALSE); + int count; + ListBase *seqbasep; + TStripElem *se; + + + if(ed==NULL) return NULL; + + count = BLI_countlist(&ed->metastack); + if((chanshown < 0) && (count > 0)) { + count = MAX2(count + chanshown, 0); + seqbasep= ((MetaStack*)BLI_findlink(&ed->metastack, count))->oldbasep; + } else { + seqbasep= ed->seqbasep; + } + + seqrectx= rectx; /* bad bad global! */ + seqrecty= recty; + + se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size); + + if(!se) { + return 0; + } + + check_limiter_refcount_comp("give_ibuf_seq_impl", se); + + return se->ibuf_comp; +} + +ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq) +{ + TStripElem* se; + + seqrectx= rectx; /* bad bad global! */ + seqrecty= recty; + + se = do_build_seq_recursively(scene, seq, cfra, render_size); + + if(!se) { + return 0; + } + + check_limiter_refcount("give_ibuf_seq_direct", se); + + if (se->ibuf) { + IMB_cache_limiter_unref(se->ibuf); + } + + return se->ibuf; +} + +ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size); + + if (i) { + IMB_cache_limiter_unref(i); + } + return i; +} + +/* check used when we need to change seq->blend_mode but not to effect or audio strips */ +int seq_can_blend(Sequence *seq) +{ + if (ELEM4(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE)) { + return 1; + } else { + return 0; + } +} + +/* *********************** threading api ******************* */ + +static ListBase running_threads; +static ListBase prefetch_wait; +static ListBase prefetch_done; + +static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t wakeup_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t wakeup_cond = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t prefetch_ready_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t prefetch_ready_cond = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t frame_done_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t frame_done_cond = PTHREAD_COND_INITIALIZER; + +static volatile int seq_thread_shutdown = FALSE; +static volatile int seq_last_given_monoton_cfra = 0; +static int monoton_cfra = 0; + +typedef struct PrefetchThread { + struct PrefetchThread *next, *prev; + + Scene *scene; + struct PrefetchQueueElem *current; + pthread_t pthread; + int running; + +} PrefetchThread; + +typedef struct PrefetchQueueElem { + struct PrefetchQueueElem *next, *prev; + + int rectx; + int recty; + int cfra; + int chanshown; + int render_size; + + int monoton_cfra; + + struct ImBuf * ibuf; +} PrefetchQueueElem; + +static void *seq_prefetch_thread(void * This_) +{ + PrefetchThread * This = This_; + + while (!seq_thread_shutdown) { + PrefetchQueueElem *e; + int s_last; + + pthread_mutex_lock(&queue_lock); + e = prefetch_wait.first; + if (e) { + BLI_remlink(&prefetch_wait, e); + } + s_last = seq_last_given_monoton_cfra; + + This->current = e; + + pthread_mutex_unlock(&queue_lock); + + if (!e) { + pthread_mutex_lock(&prefetch_ready_lock); + + This->running = FALSE; + + pthread_cond_signal(&prefetch_ready_cond); + pthread_mutex_unlock(&prefetch_ready_lock); + + pthread_mutex_lock(&wakeup_lock); + if (!seq_thread_shutdown) { + pthread_cond_wait(&wakeup_cond, &wakeup_lock); + } + pthread_mutex_unlock(&wakeup_lock); + continue; + } + + This->running = TRUE; + + if (e->cfra >= s_last) { + e->ibuf = give_ibuf_seq_impl(This->scene, + e->rectx, e->recty, e->cfra, e->chanshown, + e->render_size); + } + + pthread_mutex_lock(&queue_lock); + + BLI_addtail(&prefetch_done, e); + + for (e = prefetch_wait.first; e; e = e->next) { + if (s_last > e->monoton_cfra) { + BLI_remlink(&prefetch_wait, e); + MEM_freeN(e); + } + } + + for (e = prefetch_done.first; e; e = e->next) { + if (s_last > e->monoton_cfra) { + if (e->ibuf) { + IMB_cache_limiter_unref(e->ibuf); + } + BLI_remlink(&prefetch_done, e); + MEM_freeN(e); + } + } + + pthread_mutex_unlock(&queue_lock); + + pthread_mutex_lock(&frame_done_lock); + pthread_cond_signal(&frame_done_cond); + pthread_mutex_unlock(&frame_done_lock); + } + return 0; +} + +void seq_start_threads(Scene *scene) +{ + int i; + + running_threads.first = running_threads.last = NULL; + prefetch_wait.first = prefetch_wait.last = NULL; + prefetch_done.first = prefetch_done.last = NULL; + + seq_thread_shutdown = FALSE; + seq_last_given_monoton_cfra = monoton_cfra = 0; + + /* since global structures are modified during the processing + of one frame, only one render thread is currently possible... + + (but we code, in the hope, that we can remove this restriction + soon...) + */ + + fprintf(stderr, "SEQ-THREAD: seq_start_threads\n"); + + for (i = 0; i < 1; i++) { + PrefetchThread *t = MEM_callocN(sizeof(PrefetchThread), "prefetch_thread"); + t->scene= scene; + t->running = TRUE; + BLI_addtail(&running_threads, t); + + pthread_create(&t->pthread, NULL, seq_prefetch_thread, t); + } + + /* init malloc mutex */ + BLI_init_threads(0, 0, 0); +} + +void seq_stop_threads() +{ + PrefetchThread *tslot; + PrefetchQueueElem *e; + + fprintf(stderr, "SEQ-THREAD: seq_stop_threads()\n"); + + if (seq_thread_shutdown) { + fprintf(stderr, "SEQ-THREAD: ... already stopped\n"); + return; + } + + pthread_mutex_lock(&wakeup_lock); + + seq_thread_shutdown = TRUE; + + pthread_cond_broadcast(&wakeup_cond); + pthread_mutex_unlock(&wakeup_lock); + + for(tslot = running_threads.first; tslot; tslot= tslot->next) { + pthread_join(tslot->pthread, NULL); + } + + + for (e = prefetch_wait.first; e; e = e->next) { + BLI_remlink(&prefetch_wait, e); + MEM_freeN(e); + } + + for (e = prefetch_done.first; e; e = e->next) { + if (e->ibuf) { + IMB_cache_limiter_unref(e->ibuf); + } + BLI_remlink(&prefetch_done, e); + MEM_freeN(e); + } + + BLI_freelistN(&running_threads); + + /* deinit malloc mutex */ + BLI_end_threads(0); +} + +void give_ibuf_prefetch_request(int rectx, int recty, int cfra, int chanshown, + int render_size) +{ + PrefetchQueueElem *e; + if (seq_thread_shutdown) { + return; + } + + e = MEM_callocN(sizeof(PrefetchQueueElem), "prefetch_queue_elem"); + e->rectx = rectx; + e->recty = recty; + e->cfra = cfra; + e->chanshown = chanshown; + e->render_size = render_size; + e->monoton_cfra = monoton_cfra++; + + pthread_mutex_lock(&queue_lock); + BLI_addtail(&prefetch_wait, e); + pthread_mutex_unlock(&queue_lock); + + pthread_mutex_lock(&wakeup_lock); + pthread_cond_signal(&wakeup_cond); + pthread_mutex_unlock(&wakeup_lock); +} + +void seq_wait_for_prefetch_ready() +{ + PrefetchThread *tslot; + + if (seq_thread_shutdown) { + return; + } + + fprintf(stderr, "SEQ-THREAD: rendering prefetch frames...\n"); + + pthread_mutex_lock(&prefetch_ready_lock); + + for(;;) { + for(tslot = running_threads.first; tslot; tslot= tslot->next) { + if (tslot->running) { + break; + } + } + if (!tslot) { + break; + } + pthread_cond_wait(&prefetch_ready_cond, &prefetch_ready_lock); + } + + pthread_mutex_unlock(&prefetch_ready_lock); + + fprintf(stderr, "SEQ-THREAD: prefetch done\n"); +} + +ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size) +{ + PrefetchQueueElem *e = NULL; + int found_something = FALSE; + + if (seq_thread_shutdown) { + return give_ibuf_seq(scene, rectx, recty, cfra, chanshown, render_size); + } + + while (!e) { + int success = FALSE; + pthread_mutex_lock(&queue_lock); + + for (e = prefetch_done.first; e; e = e->next) { + if (cfra == e->cfra && + chanshown == e->chanshown && + rectx == e->rectx && + recty == e->recty && + render_size == e->render_size) { + success = TRUE; + found_something = TRUE; + break; + } + } + + if (!e) { + for (e = prefetch_wait.first; e; e = e->next) { + if (cfra == e->cfra && + chanshown == e->chanshown && + rectx == e->rectx && + recty == e->recty && + render_size == e->render_size) { + found_something = TRUE; + break; + } + } + } + + if (!e) { + PrefetchThread *tslot; + + for(tslot = running_threads.first; + tslot; tslot= tslot->next) { + if (tslot->current && + cfra == tslot->current->cfra && + chanshown == tslot->current->chanshown && + rectx == tslot->current->rectx && + recty == tslot->current->recty && + render_size== tslot->current->render_size){ + found_something = TRUE; + break; + } + } + } + + /* e->ibuf is unrefed by render thread on next round. */ + + if (e) { + seq_last_given_monoton_cfra = e->monoton_cfra; + } + + pthread_mutex_unlock(&queue_lock); + + if (!success) { + e = NULL; + + if (!found_something) { + fprintf(stderr, + "SEQ-THREAD: Requested frame " + "not in queue ???\n"); + break; + } + pthread_mutex_lock(&frame_done_lock); + pthread_cond_wait(&frame_done_cond, &frame_done_lock); + pthread_mutex_unlock(&frame_done_lock); + } + } + + return e ? e->ibuf : 0; +} + +/* Functions to free imbuf and anim data on changes */ + +static void free_imbuf_strip_elem(TStripElem *se) +{ + if(se->ibuf) { + IMB_freeImBuf(se->ibuf); + } + if(se->ibuf_comp) { + IMB_freeImBuf(se->ibuf_comp); + } + se->ibuf_comp = 0; + se->ibuf= 0; + se->ok= STRIPELEM_OK; + se->se1= se->se2= se->se3= 0; +} + +static void free_anim_seq(Sequence *seq) +{ + if(seq->anim) { + IMB_free_anim(seq->anim); + seq->anim = 0; + } +} + +void free_imbuf_seq_except(Scene *scene, int cfra) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + TStripElem *se; + int a; + + if(ed==NULL) return; + + SEQ_BEGIN(ed, seq) { + if(seq->strip) { + TStripElem * curelem = give_tstripelem(seq, cfra); + + for(a = 0, se = seq->strip->tstripdata; + a < seq->strip->len && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + for(a = 0, se = seq->strip->tstripdata_startstill; + a < seq->strip->startstill && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + for(a = 0, se = seq->strip->tstripdata_endstill; + a < seq->strip->endstill && se; a++, se++) { + if(se != curelem) { + free_imbuf_strip_elem(se); + } + } + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + if(seq->type==SEQ_MOVIE) + if(seq->startdisp > cfra || seq->enddisp < cfra) + free_anim_seq(seq); + free_proxy_seq(seq); + } + } + SEQ_END +} + +void free_imbuf_seq(ListBase * seqbase) +{ + Sequence *seq; + TStripElem *se; + int a; + + for(seq= seqbase->first; seq; seq= seq->next) { + if(seq->strip) { + for(a = 0, se = seq->strip->tstripdata; + a < seq->strip->len && se; a++, se++) { + free_imbuf_strip_elem(se); + } + for(a = 0, se = seq->strip->tstripdata_startstill; + a < seq->strip->startstill && se; a++, se++) { + free_imbuf_strip_elem(se); + } + for(a = 0, se = seq->strip->tstripdata_endstill; + a < seq->strip->endstill && se; a++, se++) { + free_imbuf_strip_elem(se); + } + if(seq->strip->ibuf_startstill) { + IMB_freeImBuf(seq->strip->ibuf_startstill); + seq->strip->ibuf_startstill = 0; + } + + if(seq->strip->ibuf_endstill) { + IMB_freeImBuf(seq->strip->ibuf_endstill); + seq->strip->ibuf_endstill = 0; + } + + if(seq->type==SEQ_MOVIE) + free_anim_seq(seq); + if(seq->type==SEQ_SPEED) { + sequence_effect_speed_rebuild_map(seq, 1); + } + } + if(seq->type==SEQ_META) { + free_imbuf_seq(&seq->seqbase); + } + } + +} + +static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change) +{ + Sequence *subseq; + int a, free_imbuf = 0; + TStripElem *se; + + /* recurs downwards to see if this seq depends on the changed seq */ + + if(seq == NULL) + return 0; + + if(seq == changed_seq) + free_imbuf = 1; + + for(subseq=seq->seqbase.first; subseq; subseq=subseq->next) + if(update_changed_seq_recurs(scene, subseq, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + + if(seq->seq1) + if(update_changed_seq_recurs(scene, seq->seq1, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + if(seq->seq2 && (seq->seq2 != seq->seq1)) + if(update_changed_seq_recurs(scene, seq->seq2, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + if(seq->seq3 && (seq->seq3 != seq->seq1) && (seq->seq3 != seq->seq2)) + if(update_changed_seq_recurs(scene, seq->seq3, changed_seq, len_change, ibuf_change)) + free_imbuf = TRUE; + + if(free_imbuf) { + if(ibuf_change) { + se= seq->strip->tstripdata; + if (se) { + for(a=0; a<seq->len; a++, se++) + free_imbuf_strip_elem(se); + } + + if(seq->type == SEQ_MOVIE) + free_anim_seq(seq); + if(seq->type == SEQ_SPEED) { + sequence_effect_speed_rebuild_map(seq, 1); + } + } + + if(len_change) + calc_sequence(seq); + } + + return free_imbuf; +} + +void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_change, int ibuf_change) +{ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + + if (ed==NULL) return; + + for (seq=ed->seqbase.first; seq; seq=seq->next) + update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change); +} + +void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo) +{ + /* force update of all sequences with this ipo, on ipo changes */ + Editing *ed= seq_give_editing(scene, FALSE); + Sequence *seq; + + if(ed==NULL) return; + + SEQ_BEGIN(ed, seq) { + if(seq->ipo == ipo) { + update_changed_seq_and_deps(scene, seq, 0, 1); + if(seq->type == SEQ_SPEED) { + sequence_effect_speed_rebuild_map(seq, 1); + } + free_proxy_seq(seq); + } + } + SEQ_END +} + +#if 0 +/* bad levell call... */ +void do_render_seq(RenderResult *rr, int cfra) +{ + ImBuf *ibuf; + + ibuf= give_ibuf_seq(scene, rr->rectx, rr->recty, cfra, 0, scene->r.size); + + if(ibuf) { + if(ibuf->rect_float) { + if (!rr->rectf) + rr->rectf= MEM_mallocN(4*sizeof(float)*rr->rectx*rr->recty, "render_seq rectf"); + + memcpy(rr->rectf, ibuf->rect_float, 4*sizeof(float)*rr->rectx*rr->recty); + + /* TSK! Since sequence render doesn't free the *rr render result, the old rect32 + can hang around when sequence render has rendered a 32 bits one before */ + if(rr->rect32) { + MEM_freeN(rr->rect32); + rr->rect32= NULL; + } + } + else if(ibuf->rect) { + if (!rr->rect32) + rr->rect32= MEM_mallocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); + + memcpy(rr->rect32, ibuf->rect, 4*rr->rectx*rr->recty); + + /* if (ibuf->zbuf) { */ + /* if (R.rectz) freeN(R.rectz); */ + /* R.rectz = BLI_dupallocN(ibuf->zbuf); */ + /* } */ + } + + /* Let the cache limitor take care of this (schlaile) */ + /* While render let's keep all memory available for render + (ton) + At least if free memory is tight... + This can make a big difference in encoding speed + (it is around 4 times(!) faster, if we do not waste time + on freeing _all_ buffers every time on long timelines...) + (schlaile) + */ + { + uintptr_t mem_in_use; + uintptr_t mmap_in_use; + uintptr_t max; + + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + max = MEM_CacheLimiter_get_maximum(); + + if (max != 0 && mem_in_use + mmap_in_use > max) { + fprintf(stderr, "Memory in use > maximum memory\n"); + fprintf(stderr, "Cleaning up, please wait...\n" + "If this happens very often,\n" + "consider " + "raising the memcache limit in the " + "user preferences.\n"); + free_imbuf_seq(); + } + free_proxy_seq(seq); + } + } + else { + /* render result is delivered empty in most cases, nevertheless we handle all cases */ + if (rr->rectf) + memset(rr->rectf, 0, 4*sizeof(float)*rr->rectx*rr->recty); + else if (rr->rect32) + memset(rr->rect32, 0, 4*rr->rectx*rr->recty); + else + rr->rect32= MEM_callocN(sizeof(int)*rr->rectx*rr->recty, "render_seq rect"); + } +} + +#endif + +/* seq funcs's for transforming internally + notice the difference between start/end and left/right. + + left and right are the bounds at which the sequence is rendered, +start and end are from the start and fixed length of the sequence. +*/ +int seq_tx_get_start(Sequence *seq) { + return seq->start; +} +int seq_tx_get_end(Sequence *seq) +{ + return seq->start+seq->len; +} + +int seq_tx_get_final_left(Sequence *seq, int metaclip) +{ + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) ); + } else { + return (seq->start - seq->startstill) + seq->startofs; + } + +} +int seq_tx_get_final_right(Sequence *seq, int metaclip) +{ + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) ); + } else { + return ((seq->start+seq->len) + seq->endstill) - seq->endofs; + } +} + +void seq_tx_set_final_left(Sequence *seq, int val) +{ + if (val < (seq)->start) { + seq->startstill = abs(val - (seq)->start); + (seq)->startofs = 0; + } else { + seq->startofs = abs(val - (seq)->start); + seq->startstill = 0; + } +} + +void seq_tx_set_final_right(Sequence *seq, int val) +{ + if (val > (seq)->start + (seq)->len) { + seq->endstill = abs(val - (seq->start + (seq)->len)); + (seq)->endofs = 0; + } else { + seq->endofs = abs(val - ((seq)->start + (seq)->len)); + seq->endstill = 0; + } +} + +/* used so we can do a quick check for single image seq + since they work a bit differently to normal image seq's (during transform) */ +int check_single_seq(Sequence *seq) +{ + if ( seq->len==1 && (seq->type == SEQ_IMAGE || seq->type == SEQ_COLOR)) + return 1; + else + return 0; +} + +/* use to impose limits when dragging/extending - so impossible situations dont happen + * Cant use the SEQ_LEFTSEL and SEQ_LEFTSEL directly because the strip may be in a metastrip */ +void seq_tx_handle_xlimits(Sequence *seq, int leftflag, int rightflag) +{ + if(leftflag) { + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) { + seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1); + } + + if (check_single_seq(seq)==0) { + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) { + seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1); + } + + /* dosnt work now - TODO */ + /* + if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { + int ofs; + ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0); + seq->start -= ofs; + seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs ); + }*/ + + } + } + + if(rightflag) { + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) { + seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1); + } + + if (check_single_seq(seq)==0) { + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) { + seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1); + } + } + } + + /* sounds cannot be extended past their endpoints */ + if (seq->type == SEQ_RAM_SOUND || seq->type == SEQ_HD_SOUND) { + seq->startstill= 0; + seq->endstill= 0; + } +} + +void fix_single_seq(Sequence *seq) +{ + int left, start, offset; + if (!check_single_seq(seq)) + return; + + /* make sure the image is always at the start since there is only one, + adjusting its start should be ok */ + left = seq_tx_get_final_left(seq, 0); + start = seq->start; + if (start != left) { + offset = left - start; + seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset ); + seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset ); + seq->start += offset; + } +} + +int seq_tx_test(Sequence * seq) +{ + return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0); +} + +int seq_test_overlap(ListBase * seqbasep, Sequence *test) +{ + Sequence *seq; + + seq= seqbasep->first; + while(seq) { + if(seq!=test) { + if(test->machine==seq->machine) { + if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) ); + else return 1; + } + } + seq= seq->next; + } + return 0; +} + + +static void seq_translate(Sequence *seq, int delta) +{ + seq->start += delta; + if(seq->type==SEQ_META) { + Sequence *seq_child; + for(seq_child= seq->seqbase.first; seq_child; seq_child= seq_child->next) { + seq_translate(seq_child, delta); + } + } + + calc_sequence_disp(seq); +} + +/* return 0 if there werent enough space */ +int shuffle_seq(ListBase * seqbasep, Sequence *test) +{ + int orig_machine= test->machine; + test->machine++; + calc_sequence(test); + while( seq_test_overlap(seqbasep, test) ) { + if(test->machine >= MAXSEQ) { + break; + } + test->machine++; + calc_sequence(test); // XXX - I dont think this is needed since were only moving vertically, Campbell. + } + + + if(test->machine >= MAXSEQ) { + /* Blender 2.4x would remove the strip. + * nicer to move it to the end */ + + Sequence *seq; + int new_frame= test->enddisp; + + for(seq= seqbasep->first; seq; seq= seq->next) { + if (seq->machine == orig_machine) + new_frame = MAX2(new_frame, seq->enddisp); + } + + test->machine= orig_machine; + new_frame = new_frame + (test->start-test->startdisp); /* adjust by the startdisp */ + seq_translate(test, new_frame - test->start); + + calc_sequence(test); + return 0; + } else { + return 1; + } +} diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 6784f014efa..27357d92aae 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -38,6 +38,7 @@ #include "DNA_modifier_types.h" #include "DNA_meshdata_types.h" #include "DNA_mesh_types.h" +#include "DNA_scene_types.h" #include "BKE_shrinkwrap.h" #include "BKE_DerivedMesh.h" @@ -47,15 +48,18 @@ #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" #include "BKE_global.h" +#include "BKE_mesh.h" #include "BKE_subsurf.h" #include "BLI_arithb.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" +#include "BLI_editVert.h" #include "RE_raytrace.h" #include "MEM_guardedalloc.h" +#include "ED_mesh.h" /* Util macros */ #define TO_STR(a) #a @@ -91,16 +95,21 @@ typedef void ( *Shrinkwrap_ForeachVertexCallback) (DerivedMesh *target, float *c /* get derived mesh */ //TODO is anyfunction that does this? returning the derivedFinal witouth we caring if its in edit mode or not? -DerivedMesh *object_get_derived_final(Object *ob, CustomDataMask dataMask) +DerivedMesh *object_get_derived_final(struct Scene *scene, Object *ob, CustomDataMask dataMask) { - if (ob==G.obedit) + Mesh *me= ob->data; + EditMesh *em = BKE_mesh_get_editmesh(me); + + if (em) { DerivedMesh *final = NULL; - editmesh_get_derived_cage_and_final(&final, dataMask); + editmesh_get_derived_cage_and_final(scene, ob, em, &final, dataMask); + + BKE_mesh_end_editmesh(me, em); return final; } else - return mesh_get_derived_final(ob, dataMask); + return mesh_get_derived_final(scene, ob, dataMask); } /* Space transform */ @@ -122,13 +131,13 @@ void space_transform_invert(const SpaceTransform *data, float *co) VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co); } -void space_transform_apply_normal(const SpaceTransform *data, float *no) +static void space_transform_apply_normal(const SpaceTransform *data, float *no) { Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } -void space_transform_invert_normal(const SpaceTransform *data, float *no) +static void space_transform_invert_normal(const SpaceTransform *data, float *no) { Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? @@ -144,117 +153,13 @@ static float squared_dist(const float *a, const float *b) return INPR(tmp, tmp); } -/* Main shrinkwrap function */ -void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) -{ - - DerivedMesh *ss_mesh = NULL; - ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; - - //remove loop dependencies on derived meshs (TODO should this be done elsewhere?) - if(smd->target == ob) smd->target = NULL; - if(smd->auxTarget == ob) smd->auxTarget = NULL; - - - //Configure Shrinkwrap calc data - calc.smd = smd; - calc.ob = ob; - calc.numVerts = numVerts; - calc.vertexCos = vertexCos; - - //DeformVertex - calc.vgroup = get_named_vertexgroup_num(calc.ob, calc.smd->vgroup_name); - if(dm) - { - calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); - } - else if(calc.ob->type == OB_LATTICE) - { - calc.dvert = lattice_get_deform_verts(calc.ob); - } - - - if(smd->target) - { - calc.target = object_get_derived_final(smd->target, CD_MASK_BAREMESH); - - //TODO there might be several "bugs" on non-uniform scales matrixs - //because it will no longer be nearest surface, not sphere projection - //because space has been deformed - space_transform_setup(&calc.local2target, ob, smd->target); - - //TODO: smd->keepDist is in global units.. must change to local - calc.keepDist = smd->keepDist; - } - - - - calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name); - - if(dm != NULL) - { - //Setup arrays to get vertexs positions, normals and deform weights - calc.vert = dm->getVertDataArray(dm, CD_MVERT); - calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); - - //Using vertexs positions/normals as if a subsurface was applied - if(smd->subsurfLevels) - { - SubsurfModifierData ssmd; - memset(&ssmd, 0, sizeof(ssmd)); - ssmd.subdivType = ME_CC_SUBSURF; //catmull clark - ssmd.levels = smd->subsurfLevels; //levels - - ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, FALSE, NULL, 0, 0); - - if(ss_mesh) - { - calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT); - if(calc.vert) - { - //TRICKY: this code assumes subsurface will have the transformed original vertices - //in their original order at the end of the vert array. - calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm); - } - } - - //Just to make sure we are not letting any memory behind - assert(ssmd.emCache == NULL); - assert(ssmd.mCache == NULL); - } - } - - //Projecting target defined - lets work! - if(calc.target) - { - switch(smd->shrinkType) - { - case MOD_SHRINKWRAP_NEAREST_SURFACE: - BENCH(shrinkwrap_calc_nearest_surface_point(&calc)); - break; - - case MOD_SHRINKWRAP_PROJECT: - BENCH(shrinkwrap_calc_normal_projection(&calc)); - break; - - case MOD_SHRINKWRAP_NEAREST_VERTEX: - BENCH(shrinkwrap_calc_nearest_vertex(&calc)); - break; - } - } - - //free memory - if(ss_mesh) - ss_mesh->release(ss_mesh); -} - /* * Shrinkwrap to the nearest vertex * * it builds a kdtree of vertexs we can attach to and then * for each vertex performs a nearest vertex search on the tree */ -void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) +static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) { int i; @@ -272,8 +177,9 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) //Setup nearest nearest.index = -1; nearest.dist = FLT_MAX; - +#ifndef __APPLE__ #pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData,calc) schedule(static) +#endif for(i = 0; i<calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -389,7 +295,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa } -void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) +static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, struct Scene *scene) { int i; @@ -434,7 +340,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) if(calc->smd->auxTarget) { - auxMesh = object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH); + auxMesh = object_get_derived_final(scene, calc->smd->auxTarget, CD_MASK_BAREMESH); space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget); } @@ -443,7 +349,9 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) && (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6))) { +#ifndef __APPLE__ #pragma omp parallel for private(i,hit) schedule(static) +#endif for(i = 0; i<calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -511,7 +419,7 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) * it builds a BVHTree from the target mesh and then performs a * NN matchs for each vertex */ -void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) +static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) { int i; @@ -532,7 +440,9 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) //Find the nearest vertex +#ifndef __APPLE__ #pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc,treeData) schedule(static) +#endif for(i = 0; i<calc->numVerts; ++i) { float *co = calc->vertexCos[i]; @@ -590,3 +500,107 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) free_bvhtree_from_mesh(&treeData); } +/* Main shrinkwrap function */ +void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) +{ + + DerivedMesh *ss_mesh = NULL; + ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; + + //remove loop dependencies on derived meshs (TODO should this be done elsewhere?) + if(smd->target == ob) smd->target = NULL; + if(smd->auxTarget == ob) smd->auxTarget = NULL; + + + //Configure Shrinkwrap calc data + calc.smd = smd; + calc.ob = ob; + calc.numVerts = numVerts; + calc.vertexCos = vertexCos; + + //DeformVertex + calc.vgroup = get_named_vertexgroup_num(calc.ob, calc.smd->vgroup_name); + if(dm) + { + calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + } + else if(calc.ob->type == OB_LATTICE) + { + calc.dvert = lattice_get_deform_verts(calc.ob); + } + + + if(smd->target) + { + calc.target = object_get_derived_final(scene, smd->target, CD_MASK_BAREMESH); + + //TODO there might be several "bugs" on non-uniform scales matrixs + //because it will no longer be nearest surface, not sphere projection + //because space has been deformed + space_transform_setup(&calc.local2target, ob, smd->target); + + //TODO: smd->keepDist is in global units.. must change to local + calc.keepDist = smd->keepDist; + } + + + + calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name); + + if(dm != NULL && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) + { + //Setup arrays to get vertexs positions, normals and deform weights + calc.vert = dm->getVertDataArray(dm, CD_MVERT); + calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + //Using vertexs positions/normals as if a subsurface was applied + if(smd->subsurfLevels) + { + SubsurfModifierData ssmd; + memset(&ssmd, 0, sizeof(ssmd)); + ssmd.subdivType = ME_CC_SUBSURF; //catmull clark + ssmd.levels = smd->subsurfLevels; //levels + + ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, FALSE, NULL, 0, 0); + + if(ss_mesh) + { + calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT); + if(calc.vert) + { + //TRICKY: this code assumes subsurface will have the transformed original vertices + //in their original order at the end of the vert array. + calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm); + } + } + + //Just to make sure we are not letting any memory behind + assert(ssmd.emCache == NULL); + assert(ssmd.mCache == NULL); + } + } + + //Projecting target defined - lets work! + if(calc.target) + { + switch(smd->shrinkType) + { + case MOD_SHRINKWRAP_NEAREST_SURFACE: + BENCH(shrinkwrap_calc_nearest_surface_point(&calc)); + break; + + case MOD_SHRINKWRAP_PROJECT: + BENCH(shrinkwrap_calc_normal_projection(&calc, scene)); + break; + + case MOD_SHRINKWRAP_NEAREST_VERTEX: + BENCH(shrinkwrap_calc_nearest_vertex(&calc)); + break; + } + } + + //free memory + if(ss_mesh) + ss_mesh->release(ss_mesh); +} + diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index f63f6edf4b3..bc6b487080c 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -83,8 +83,8 @@ variables on the UI for now #include "BKE_pointcache.h" #include "BKE_modifier.h" -#include "BIF_editdeform.h" -#include "BIF_graphics.h" +//XXX #include "BIF_editdeform.h" +//XXX #include "BIF_graphics.h" #include "PIL_time.h" // #include "ONL_opennl.h" remove linking to ONL for now @@ -120,7 +120,8 @@ typedef struct SBScratch { float aabbmin[3],aabbmax[3]; }SBScratch; -typedef struct SB_thread_context{ +typedef struct SB_thread_context { + Scene *scene; Object *ob; float forcetime; float timenow; @@ -196,7 +197,7 @@ static float sb_time_scale(Object *ob) /* this would be frames/sec independant timing assuming 25 fps is default but does not work very well with NLA - return (25.0f/G.scene->r.frs_sec) + return (25.0f/scene->r.frs_sec) */ } /*--- frame based timing ---*/ @@ -484,12 +485,11 @@ static void ccd_mesh_free(ccd_Mesh *ccdm) } } -static void ccd_build_deflector_hache(Object *vertexowner,GHash *hash) +static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash) { - Base *base; + Base *base= scene->base.first; Object *ob; - base= G.scene->base.first; - base= G.scene->base.first; + if (!hash) return; while (base) { /*Only proceed for mesh object in same layer */ @@ -516,9 +516,9 @@ static void ccd_build_deflector_hache(Object *vertexowner,GHash *hash) } else { if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */ - dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); else - dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); } if(dm){ @@ -536,12 +536,11 @@ static void ccd_build_deflector_hache(Object *vertexowner,GHash *hash) } /* while (base) */ } -static void ccd_update_deflector_hache(Object *vertexowner,GHash *hash) +static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash) { - Base *base; + Base *base= scene->base.first; Object *ob; - base= G.scene->base.first; - base= G.scene->base.first; + if ((!hash) || (!vertexowner)) return; while (base) { /*Only proceed for mesh object in same layer */ @@ -558,9 +557,9 @@ static void ccd_update_deflector_hache(Object *vertexowner,GHash *hash) DerivedMesh *dm= NULL; if(ob->softflag & OB_SB_COLLFINAL) { /* so maybe someone wants overkill to collide with subsurfed */ - dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); } else { - dm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); } if(dm){ ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash,ob); @@ -830,12 +829,12 @@ static void calculate_collision_balls(Object *ob) /* creates new softbody if didn't exist yet, makes new points and springs arrays */ -static void renew_softbody(Object *ob, int totpoint, int totspring) +static void renew_softbody(Scene *scene, Object *ob, int totpoint, int totspring) { SoftBody *sb; int i; short softflag; - if(ob->soft==NULL) ob->soft= sbNew(); + if(ob->soft==NULL) ob->soft= sbNew(scene); else free_softbody_intern(ob->soft); sb= ob->soft; softflag=ob->softflag; @@ -970,11 +969,11 @@ static void Vec3PlusStVec(float *v, float s, float *v1) /* +++ dependancy information functions*/ -static int are_there_deflectors(unsigned int layer) +static int are_there_deflectors(Scene *scene, unsigned int layer) { Base *base; - for(base = G.scene->base.first; base; base= base->next) { + for(base = scene->base.first; base; base= base->next) { if( (base->lay & layer) && base->object->pd) { if(base->object->pd->deflect) return 1; @@ -983,9 +982,9 @@ static int are_there_deflectors(unsigned int layer) return 0; } -static int query_external_colliders(Object *me) +static int query_external_colliders(Scene *scene, Object *me) { - return(are_there_deflectors(me->lay)); + return(are_there_deflectors(scene, me->lay)); } /* --- dependancy information functions*/ @@ -1528,9 +1527,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3],float edge_v2[3],floa return deflected; } - - -static void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int ilast, struct ListBase *do_effector) +static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, int ifirst, int ilast, struct ListBase *do_effector) { SoftBody *sb = ob->soft; int a; @@ -1569,7 +1566,7 @@ static void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int float pos[3]; VecMidf(pos, sb->bpoint[bs->v1].pos , sb->bpoint[bs->v2].pos); VecMidf(vel, sb->bpoint[bs->v1].vec , sb->bpoint[bs->v2].vec); - pdDoEffectors(do_effector, pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pdDoEffectors(scene, do_effector, pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); VecMulf(speed,windfactor); VecAddf(vel,vel,speed); } @@ -1601,26 +1598,27 @@ static void _scan_for_ext_spring_forces(Object *ob,float timenow,int ifirst,int } -static void scan_for_ext_spring_forces(Object *ob,float timenow) +static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow) { SoftBody *sb = ob->soft; ListBase *do_effector= NULL; - do_effector= pdInitEffectors(ob,NULL); + + do_effector= pdInitEffectors(scene, ob,NULL); if (sb){ - _scan_for_ext_spring_forces(ob,timenow,0,sb->totspring,do_effector); + _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); } if(do_effector) - pdEndEffectors(do_effector); + pdEndEffectors(do_effector); } static void *exec_scan_for_ext_spring_forces(void *data) { SB_thread_context *pctx = (SB_thread_context*)data; - _scan_for_ext_spring_forces(pctx->ob,pctx->timenow,pctx->ifirst,pctx->ilast,pctx->do_effector); + _scan_for_ext_spring_forces(pctx->scene, pctx->ob, pctx->timenow, pctx->ifirst, pctx->ilast, pctx->do_effector); return 0; } -static void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) +static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) { ListBase *do_effector = NULL; ListBase threads; @@ -1628,11 +1626,11 @@ static void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings int i, totthread,left,dec; int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ - do_effector= pdInitEffectors(ob,NULL); + do_effector= pdInitEffectors(scene, ob,NULL); /* figure the number of threads while preventing pretty pointless threading overhead */ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; + if(scene->r.mode & R_FIXED_THREADS) + totthread= scene->r.threads; else totthread= BLI_system_thread_count(); /* what if we got zillions of CPUs running but less to spread*/ @@ -1645,6 +1643,7 @@ static void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings left = totsprings; dec = totsprings/totthread +1; for(i=0; i<totthread; i++) { + sb_threads[i].scene = scene; sb_threads[i].ob = ob; sb_threads[i].forcetime = 0.0; // not used here sb_threads[i].timenow = timenow; @@ -2119,13 +2118,14 @@ static void sb_spring_force(Object *ob,int bpi,BodySpring *bs,float iks,float fo /* since this is definitely the most CPU consuming task here .. try to spread it */ /* core function _softbody_calc_forces_slice_in_a_thread */ /* result is int to be able to flag user break */ -static int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *ptr_to_break_func(),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) +static int _softbody_calc_forces_slice_in_a_thread(Scene *scene, Object *ob, float forcetime, float timenow,int ifirst,int ilast,int *ptr_to_break_func(),ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) { float iks; int bb,do_selfcollision,do_springcollision,do_aero; int number_of_points_here = ilast - ifirst; SoftBody *sb= ob->soft; /* is supposed to be there */ BodyPoint *bp; + /* intitialize */ if (sb) { /* check conditions for various options */ @@ -2247,7 +2247,7 @@ static int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float speed[3]= {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ - pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pdDoEffectors(scene, do_effector, bp->pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); /* apply forcefield*/ VecMulf(force,fieldfactor* eval_sb_fric_force_scale); @@ -2322,11 +2322,11 @@ return 0; /*done fine*/ static void *exec_softbody_calc_forces(void *data) { SB_thread_context *pctx = (SB_thread_context*)data; - _softbody_calc_forces_slice_in_a_thread(pctx->ob,pctx->forcetime,pctx->timenow,pctx->ifirst,pctx->ilast,NULL,pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor); + _softbody_calc_forces_slice_in_a_thread(pctx->scene, pctx->ob, pctx->forcetime, pctx->timenow, pctx->ifirst, pctx->ilast, NULL, pctx->do_effector,pctx->do_deflector,pctx->fieldfactor,pctx->windfactor); return 0; } -static void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int totpoint,int *ptr_to_break_func(),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) +static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float timenow,int totpoint,int *ptr_to_break_func(),struct ListBase *do_effector,int do_deflector,float fieldfactor, float windfactor) { ListBase threads; SB_thread_context *sb_threads; @@ -2334,8 +2334,8 @@ static void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow, int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ /* figure the number of threads while preventing pretty pointless threading overhead */ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; + if(scene->r.mode & R_FIXED_THREADS) + totthread= scene->r.threads; else totthread= BLI_system_thread_count(); /* what if we got zillions of CPUs running but less to spread*/ @@ -2383,7 +2383,7 @@ static void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow, MEM_freeN(sb_threads); } -static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, int nl_flags) +static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow, int nl_flags) { /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2398,7 +2398,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i gravity = sb->grav * sb_grav_force_scale(ob); /* check conditions for various options */ - do_deflector= query_external_colliders(ob); + do_deflector= query_external_colliders(scene, ob); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2407,17 +2407,17 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i bproot= sb->bpoint; /* need this for proper spring addressing */ if (do_springcollision || do_aero) - sb_sfesf_threads_run(ob,timenow,sb->totspring,NULL); + sb_sfesf_threads_run(scene, ob, timenow,sb->totspring,NULL); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(ob,NULL); + do_effector= pdInitEffectors(scene, ob,NULL); if (do_deflector) { float defforce[3]; do_deflector = sb_detect_aabb_collisionCached(defforce,ob->lay,ob,timenow); } - sb_cf_threads_run(ob,forcetime,timenow,sb->totpoint,NULL,do_effector,do_deflector,fieldfactor,windfactor); + sb_cf_threads_run(scene, ob, forcetime, timenow, sb->totpoint, NULL, do_effector, do_deflector, fieldfactor, windfactor); /* finally add forces caused by face collision */ if (ob->softflag & OB_SB_FACECOLL) scan_for_ext_face_forces(ob,timenow); @@ -2429,11 +2429,11 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i -static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags) +static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow, int nl_flags) { /* redirection to the new threaded Version */ if (!(G.rt & 0x10)){ // 16 - softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags); + softbody_calc_forcesEx(scene, ob, forcetime, timenow, nl_flags); return; } else{ @@ -2472,7 +2472,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int gravity = sb->grav * sb_grav_force_scale(ob); /* check conditions for various options */ - do_deflector= query_external_colliders(ob); + do_deflector= query_external_colliders(scene, ob); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2480,9 +2480,9 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ bproot= sb->bpoint; /* need this for proper spring addressing */ - if (do_springcollision || do_aero) scan_for_ext_spring_forces(ob,timenow); + if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(ob,NULL); + do_effector= pdInitEffectors(scene, ob,NULL); if (do_deflector) { float defforce[3]; @@ -2650,7 +2650,7 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int float speed[3]= {0.0f, 0.0f, 0.0f}; float eval_sb_fric_force_scale = sb_fric_force_scale(ob); /* just for calling function once */ - pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + pdDoEffectors(scene, do_effector, bp->pos, force, speed, (float)scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); /* apply forcefield*/ VecMulf(force,fieldfactor* eval_sb_fric_force_scale); @@ -3075,8 +3075,8 @@ static void apply_spring_memory(Object *ob) int a; float b,l,r; - b = sb->plastic; if (sb && sb->totspring){ + b = sb->plastic; for(a=0; a<sb->totspring; a++) { bs = &sb->bspring[a]; bp1 =&sb->bpoint[bs->v1]; @@ -3191,7 +3191,7 @@ static void springs_from_mesh(Object *ob) /* makes totally fresh start situation */ -static void mesh_to_softbody(Object *ob) +static void mesh_to_softbody(Scene *scene, Object *ob) { SoftBody *sb; Mesh *me= ob->data; @@ -3204,7 +3204,7 @@ static void mesh_to_softbody(Object *ob) else totedge= 0; /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(ob, me->totvert, totedge); + renew_softbody(scene, ob, me->totvert, totedge); /* we always make body points */ sb= ob->soft; @@ -3391,7 +3391,7 @@ static void makelatticesprings(Lattice *lt, BodySpring *bs, int dostiff,Object * /* makes totally fresh start situation */ -static void lattice_to_softbody(Object *ob) +static void lattice_to_softbody(Scene *scene, Object *ob) { Lattice *lt= ob->data; SoftBody *sb; @@ -3410,7 +3410,7 @@ static void lattice_to_softbody(Object *ob) /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(ob, totvert, totspring); + renew_softbody(scene, ob, totvert, totspring); sb= ob->soft; /* can be created in renew_softbody() */ /* weights from bpoints, same code used as for mesh vertices */ @@ -3435,7 +3435,7 @@ static void lattice_to_softbody(Object *ob) } /* makes totally fresh start situation */ -static void curve_surf_to_softbody(Object *ob) +static void curve_surf_to_softbody(Scene *scene, Object *ob) { Curve *cu= ob->data; SoftBody *sb; @@ -3457,7 +3457,7 @@ static void curve_surf_to_softbody(Object *ob) } /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(ob, totvert, totspring); + renew_softbody(scene, ob, totvert, totspring); sb= ob->soft; /* can be created in renew_softbody() */ /* set vars now */ @@ -3546,9 +3546,9 @@ static void springs_from_particles(Object *ob) int a,k; float hairmat[4][4]; - psys= ob->soft->particles; - sb= ob->soft; - if(ob && sb && psys) { + if(ob && ob->soft && ob->soft->particles) { + psys= ob->soft->particles; + sb= ob->soft; psmd = psys_get_modifier(ob, psys); bp= sb->bpoint; @@ -3567,7 +3567,7 @@ static void springs_from_particles(Object *ob) } } -static void particles_to_softbody(Object *ob) +static void particles_to_softbody(Scene *scene, Object *ob) { SoftBody *sb; BodyPoint *bp; @@ -3581,7 +3581,7 @@ static void particles_to_softbody(Object *ob) int totedge= totpoint-psys->totpart; /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */ - renew_softbody(ob, totpoint, totedge); + renew_softbody(scene, ob, totpoint, totedge); /* find first BodyPoint index for each particle */ if(psys->totpart > 0) { @@ -3727,7 +3727,7 @@ static void sb_new_scratch(SoftBody *sb) /* ************ Object level, exported functions *************** */ /* allocates and initializes general main data */ -SoftBody *sbNew(void) +SoftBody *sbNew(Scene *scene) { SoftBody *sb; @@ -3751,8 +3751,8 @@ SoftBody *sbNew(void) sb->inpush = 0.5f; sb->interval= 10; - sb->sfra= G.scene->r.sfra; - sb->efra= G.scene->r.efra; + sb->sfra= scene->r.sfra; + sb->efra= scene->r.efra; sb->colball = 0.49f; sb->balldamp = 0.50f; @@ -3938,16 +3938,17 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int } } -static void softbody_step(Object *ob, SoftBody *sb, float dtime) +static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) { /* the simulator */ float forcetime; double sct,sst=PIL_check_seconds_timer(); - ccd_update_deflector_hache(ob,sb->scratch->colliderhash); + + ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash); if(sb->scratch->needstobuildcollider){ - if (query_external_colliders(ob)){ - ccd_build_deflector_hache(ob,sb->scratch->colliderhash); + if (query_external_colliders(scene, ob)){ + ccd_build_deflector_hash(scene, ob, sb->scratch->colliderhash); } sb->scratch->needstobuildcollider=0; } @@ -3980,12 +3981,12 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime) sb->scratch->flag &= ~SBF_DOFUZZY; /* do predictive euler step */ - softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_calc_forces(scene, ob, forcetime,timedone/dtime,0); softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags); /* crop new slope values to do averaged slope step */ - softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_calc_forces(scene, ob, forcetime,timedone/dtime,0); softbody_apply_forces(ob, forcetime, 2, &err,mid_flags); softbody_apply_goalsnap(ob); @@ -4067,7 +4068,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime) } /* simulates one step. framenr is in frames */ -void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) +void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) { ParticleSystemModifierData *psmd=0; ParticleData *pa=0; @@ -4083,7 +4084,7 @@ void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) framedelta= framenr - cache->simframe; BKE_ptcache_id_from_softbody(&pid, ob, sb); - BKE_ptcache_id_time(&pid, framenr, &startframe, &endframe, ×cale); + BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); /* check for changes in mesh, should only happen in case the mesh * structure changes during an animation */ @@ -4110,22 +4111,22 @@ void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) { if(sb->particles){ - particles_to_softbody(ob); + particles_to_softbody(scene, ob); } else { switch(ob->type) { case OB_MESH: - mesh_to_softbody(ob); + mesh_to_softbody(scene, ob); break; case OB_LATTICE: - lattice_to_softbody(ob); + lattice_to_softbody(scene, ob); break; case OB_CURVE: case OB_SURF: - curve_surf_to_softbody(ob); + curve_surf_to_softbody(scene, ob); break; default: - renew_softbody(ob, numVerts, 0); + renew_softbody(scene, ob, numVerts, 0); break; } } @@ -4143,7 +4144,7 @@ void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) dtime = timescale; softbody_update_positions(ob, sb, vertexCos, numVerts); - softbody_step(ob, sb, dtime); + softbody_step(scene, ob, sb, dtime); if(sb->particles==0) softbody_to_object(ob, vertexCos, numVerts, 0); @@ -4203,7 +4204,7 @@ void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) /* checking time: */ dtime = framedelta*timescale; - softbody_step(ob, sb, dtime); + softbody_step(scene, ob, sb, dtime); if(sb->particles==0) softbody_to_object(ob, vertexCos, numVerts, 0); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index f79009e673d..15969fc9ab9 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -41,7 +41,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" @@ -49,6 +48,7 @@ #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_multires.h" #include "BKE_scene.h" #include "BKE_subsurf.h" @@ -472,7 +472,7 @@ static void calc_ss_weights(int gridFaces, static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, int drawInteriorEdges, int useSubsurfUv, - DerivedMesh *dm) + DerivedMesh *dm, MultiresSubsurf *ms) { DerivedMesh *result; int edgeSize = ccgSubSurf_getEdgeSize(ss); @@ -525,14 +525,21 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, } ccgFaceIterator_free(fi); - if(dm) { - result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); - } else { - result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), - ccgSubSurf_getNumFinalEdges(ss), - ccgSubSurf_getNumFinalFaces(ss)); + if(ms) { + result = MultiresDM_new(ms, dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } + else { + if(dm) { + result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } else { + result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss), + ccgSubSurf_getNumFinalEdges(ss), + ccgSubSurf_getNumFinalFaces(ss)); + } } // load verts @@ -558,11 +565,12 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, ++mvert; ++origIndex; i++; - + for(S = 0; S < numVerts; S++) { int prevS = (S - 1 + numVerts) % numVerts; int nextS = (S + 1) % numVerts; int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + for(x = 1; x < gridFaces; x++) { float w[4]; w[prevS] = weight[x][0][0]; @@ -572,6 +580,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i); VecCopyf(mvert->co, ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); + *origIndex = ORIGINDEX_NONE; ++mvert; ++origIndex; @@ -583,6 +592,7 @@ static DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, int prevS = (S - 1 + numVerts) % numVerts; int nextS = (S + 1) % numVerts; int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3; + for(y = 1; y < gridFaces; y++) { for(x = 1; x < gridFaces; x++) { float w[4]; @@ -881,8 +891,8 @@ static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, static int hasGivenError = 0; if(!hasGivenError) { - error("Unrecoverable error in SubSurf calculation," - " mesh is inconsistent."); + //XXX error("Unrecoverable error in SubSurf calculation," + // " mesh is inconsistent."); hasGivenError = 1; } @@ -2566,9 +2576,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, /***/ -struct DerivedMesh *subsurf_make_derived_from_derived( +struct DerivedMesh *subsurf_make_derived_from_derived_with_multires( struct DerivedMesh *dm, struct SubsurfModifierData *smd, + struct MultiresSubsurf *ms, int useRenderParams, float (*vertCos)[3], int isFinalCalc, int editMode) { @@ -2591,7 +2602,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( CCGSubSurf *ss; int levels; - levels= get_render_subsurf_level(&G.scene->r, smd->renderLevels); + levels= smd->renderLevels; // XXX get_render_subsurf_level(&scene->r, smd->renderLevels); if(levels == 0) return dm; @@ -2600,7 +2611,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); ccgSubSurf_free(ss); @@ -2631,7 +2642,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); /*return (DerivedMesh *)getCCGDerivedMesh(smd->mCache, drawInteriorEdges, @@ -2651,7 +2662,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( useSubsurfUv, dm);*/ result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges, - useSubsurfUv, dm); + useSubsurfUv, dm, ms); ccgSubSurf_free(ss); @@ -2660,6 +2671,15 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } } +struct DerivedMesh *subsurf_make_derived_from_derived( + struct DerivedMesh *dm, + struct SubsurfModifierData *smd, + int useRenderParams, float (*vertCos)[3], + int isFinalCalc, int editMode) +{ + return subsurf_make_derived_from_derived_with_multires(dm, smd, NULL, useRenderParams, vertCos, isFinalCalc, editMode); +} + void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) { /* Finds the subsurf limit positions for the verts in a mesh diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index d33721541f8..8e3d59bbc58 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -40,7 +40,6 @@ #include "DNA_scene_types.h" #include "DNA_text_types.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BKE_text.h" #include "BKE_library.h" @@ -66,9 +65,6 @@ A text should relate to a file as follows - (Text *)->flags has the following bits TXT_ISDIRTY - should always be set if the file in mem. differs from the file on disk, or if there is no file on disk. - TXT_ISTMP - should always be set if the (Text *)->name file has not - been written before, and attempts to save should result - in "Save over?" TXT_ISMEM - should always be set if the Text has not been mapped to a file, in which case (Text *)->name may be NULL or garbage. TXT_ISEXT - should always be set if the Text is not to be written into @@ -131,7 +127,6 @@ static void txt_delete_line(Text *text, TextLine *line); /***/ -static char *txt_cut_buffer= NULL; static unsigned char undoing; /* allow to switch off undoing externally */ @@ -180,7 +175,7 @@ Text *add_empty_text(char *name) ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf"); ta->nlines=1; - ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM; + ta->flags= TXT_ISDIRTY | TXT_ISMEM; ta->lines.first= ta->lines.last= NULL; ta->markers.first= ta->markers.last= NULL; @@ -258,8 +253,6 @@ int reopen_text(Text *text) text->undo_len= TXT_INIT_UNDO; text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); - text->flags= TXT_ISTMP; - fseek(fp, 0L, SEEK_END); len= ftell(fp); fseek(fp, 0L, SEEK_SET); @@ -323,7 +316,7 @@ int reopen_text(Text *text) return 1; } -Text *add_text(char *file) +Text *add_text(char *file, const char *relpath) { FILE *fp; int i, llen, len, res; @@ -335,8 +328,8 @@ Text *add_text(char *file) struct stat st; BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE); - if (G.scene) /* can be NULL (bg mode) */ - BLI_convertstringcode(str, G.sce); + if (relpath) /* can be NULL (bg mode) */ + BLI_convertstringcode(str, relpath); BLI_split_dirfile_basic(str, NULL, sfile); fp= fopen(str, "r"); @@ -348,9 +341,6 @@ Text *add_text(char *file) ta->lines.first= ta->lines.last= NULL; ta->markers.first= ta->markers.last= NULL; ta->curl= ta->sell= NULL; - -/* ta->flags= TXT_ISTMP | TXT_ISEXT; */ - ta->flags= TXT_ISTMP; fseek(fp, 0L, SEEK_END); len= ftell(fp); @@ -431,7 +421,7 @@ Text *copy_text(Text *ta) tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name"); strcpy(tan->name, ta->name); - tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP; + tan->flags = ta->flags | TXT_ISDIRTY; tan->lines.first= tan->lines.last= NULL; tan->markers.first= tan->markers.last= NULL; @@ -1057,11 +1047,6 @@ void txt_sel_line (Text *text) /* Cut and paste functions */ /***************************/ -void txt_print_cutbuffer (void) -{ - printf ("Cut buffer\n--\n%s\n--\n", txt_cut_buffer); -} - char *txt_to_buf (Text *text) { int length; @@ -1166,15 +1151,6 @@ int txt_find_string(Text *text, char *findstr, int wrap) return 0; } -void txt_cut_sel (Text *text) -{ - if (!G.background) /* Python uses txt_cut_sel, which it should not, working around for now */ - txt_copy_clipboard(text); - - txt_delete_sel(text); - txt_make_dirty(text); -} - char *txt_sel_to_buf (Text *text) { char *buf; @@ -1252,85 +1228,6 @@ char *txt_sel_to_buf (Text *text) return buf; } -void txt_copy_sel (Text *text) -{ - int length=0; - TextLine *tmp, *linef, *linel; - int charf, charl; - - if (!text) return; - if (!text->curl) return; - if (!text->sell) return; - - if (!txt_has_sel(text)) return; - - if (txt_cut_buffer) MEM_freeN(txt_cut_buffer); - txt_cut_buffer= NULL; - - if (text->curl==text->sell) { - linef= linel= text->curl; - - if (text->curc < text->selc) { - charf= text->curc; - charl= text->selc; - } else{ - charf= text->selc; - charl= text->curc; - } - } else if (txt_get_span(text->curl, text->sell)<0) { - linef= text->sell; - linel= text->curl; - - charf= text->selc; - charl= text->curc; - } else { - linef= text->curl; - linel= text->sell; - - charf= text->curc; - charl= text->selc; - } - - if (linef == linel) { - length= charl-charf; - - txt_cut_buffer= MEM_mallocN(length+1, "cut buffera"); - - BLI_strncpy(txt_cut_buffer, linef->line + charf, length+1); - } else { - length+= linef->len - charf; - length+= charl; - length++; /* For the '\n' */ - - tmp= linef->next; - while (tmp && tmp!= linel) { - length+= tmp->len+1; - tmp= tmp->next; - } - - txt_cut_buffer= MEM_mallocN(length+1, "cut bufferb"); - - strncpy(txt_cut_buffer, linef->line+ charf, linef->len-charf); - length= linef->len-charf; - - txt_cut_buffer[length++]='\n'; - - tmp= linef->next; - while (tmp && tmp!=linel) { - strncpy(txt_cut_buffer+length, tmp->line, tmp->len); - length+= tmp->len; - - txt_cut_buffer[length++]='\n'; - - tmp= tmp->next; - } - strncpy(txt_cut_buffer+length, linel->line, charl); - length+= charl; - - txt_cut_buffer[length]=0; - } -} - void txt_insert_buf(Text *text, char *in_buffer) { int i=0, l=0, j, u, len; @@ -1381,38 +1278,32 @@ void txt_insert_buf(Text *text, char *in_buffer) undoing= u; } -void txt_free_cut_buffer(void) -{ - if (txt_cut_buffer) MEM_freeN(txt_cut_buffer); -} - -void txt_paste(Text *text) -{ - txt_insert_buf(text, txt_cut_buffer); -} - /******************/ /* Undo functions */ /******************/ -#define MAX_UNDO_TEST(x) \ - while (text->undo_pos+x >= text->undo_len) { \ - if(text->undo_len*2 > TXT_MAX_UNDO) { \ - error("Undo limit reached, buffer cleared\n"); \ - MEM_freeN(text->undo_buf); \ - text->undo_len= TXT_INIT_UNDO; \ - text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); \ - text->undo_pos=-1; \ - return; \ - } else { \ - void *tmp= text->undo_buf; \ - text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); \ - memcpy(text->undo_buf, tmp, text->undo_len); \ - text->undo_len*=2; \ - MEM_freeN(tmp); \ - } \ +static int max_undo_test(Text *text, int x) +{ + while (text->undo_pos+x >= text->undo_len) { + if(text->undo_len*2 > TXT_MAX_UNDO) { + /* XXX error("Undo limit reached, buffer cleared\n"); */ + MEM_freeN(text->undo_buf); + text->undo_len= TXT_INIT_UNDO; + text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); + text->undo_pos=-1; + return 0; + } else { + void *tmp= text->undo_buf; + text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); + memcpy(text->undo_buf, tmp, text->undo_len); + text->undo_len*=2; + MEM_freeN(tmp); + } } + return 1; +} + static void dump_buffer(Text *text) { int i= 0; @@ -1558,7 +1449,8 @@ void txt_print_undo(Text *text) static void txt_undo_add_op(Text *text, int op) { - MAX_UNDO_TEST(2); + if(!max_undo_test(text, 2)) + return; text->undo_pos++; text->undo_buf[text->undo_pos]= op; @@ -1571,7 +1463,8 @@ static void txt_undo_add_block(Text *text, int op, char *buf) length= strlen(buf); - MAX_UNDO_TEST(length+11); + if(!max_undo_test(text, length+11)) + return; text->undo_pos++; text->undo_buf[text->undo_pos]= op; @@ -1605,7 +1498,8 @@ static void txt_undo_add_block(Text *text, int op, char *buf) void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) { - MAX_UNDO_TEST(15); + if(!max_undo_test(text, 15)) + return; if (froml==tol && fromc==toc) return; @@ -1648,7 +1542,8 @@ void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fr static void txt_undo_add_charop(Text *text, int op, char c) { - MAX_UNDO_TEST(4); + if(!max_undo_test(text, 4)) + return; text->undo_pos++; text->undo_buf[text->undo_pos]= op; @@ -1869,7 +1764,7 @@ void txt_do_undo(Text *text) text->undo_pos--; break; default: - error("Undo buffer error - resetting"); + //XXX error("Undo buffer error - resetting"); text->undo_pos= -1; break; @@ -2082,7 +1977,7 @@ void txt_do_redo(Text *text) } break; default: - error("Undo buffer error - resetting"); + //XXX error("Undo buffer error - resetting"); text->undo_pos= -1; break; @@ -2395,6 +2290,12 @@ int txt_add_char (Text *text, char add) return 1; } +void txt_delete_selected(Text *text) +{ + txt_delete_sel(text); + txt_make_dirty(text); +} + int txt_replace_char (Text *text, char add) { char del; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 52b88de06e0..66f7fe8a44b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -61,7 +61,6 @@ #include "BKE_plugin_types.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BKE_global.h" @@ -73,9 +72,9 @@ #include "BKE_texture.h" #include "BKE_key.h" #include "BKE_icons.h" -#include "BKE_ipo.h" #include "BKE_brush.h" #include "BKE_node.h" +#include "BKE_animsys.h" /* ------------------------------------------------------------------------- */ @@ -177,8 +176,8 @@ PluginTex *add_plugin_tex(char *str) open_plugin_tex(pit); if(pit->doit==0) { - if(pit->handle==0) error("no plugin: %s", str); - else error("in plugin: %s", str); + if(pit->handle==0); //XXX error("no plugin: %s", str); + else ; //XXX error("in plugin: %s", str); MEM_freeN(pit); return NULL; } @@ -571,7 +570,9 @@ Tex *copy_texture(Tex *tex) if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima); else texn->ima= 0; +#if 0 // XXX old animation system id_us_plus((ID *)texn->ipo); +#endif // XXX old animation system if(texn->plugin) { texn->plugin= MEM_dupallocN(texn->plugin); @@ -733,7 +734,9 @@ void make_local_texture(Tex *tex) void autotexname(Tex *tex) { -/* extern char texstr[20][12]; *//* buttons.c, already in bad lev calls*/ + char texstr[20][12]= {"None" , "Clouds" , "Wood", "Marble", "Magic" , "Blend", + "Stucci", "Noise" , "Image", "Plugin", "EnvMap" , "Musgrave", + "Voronoi", "DistNoise", "", "", "", "", "", ""}; Image *ima; char di[FILE_MAXDIR], fi[FILE_MAXFILE]; @@ -813,14 +816,14 @@ Tex *give_current_texture(Object *ob, int act) return tex; } -Tex *give_current_world_texture(void) +Tex *give_current_world_texture(Scene *scene) { MTex *mtex = 0; Tex *tex = 0; - if(!(G.scene->world)) return 0; + if(!(scene->world)) return 0; - mtex= G.scene->world->mtex[(int)(G.scene->world->texact)]; + mtex= scene->world->mtex[(int)(scene->world->texact)]; if(mtex) tex= mtex->tex; return tex; @@ -887,13 +890,17 @@ int BKE_texture_dependsOnTime(const struct Tex *texture) if(texture->plugin) { // assume all plugins depend on time return 1; - } else if( texture->ima && + } + else if( texture->ima && ELEM(texture->ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { return 1; - } else if(texture->ipo) { + } +#if 0 // XXX old animation system + else if(texture->ipo) { // assume any ipo means the texture is animated return 1; } +#endif // XXX old animation system return 0; } diff --git a/source/blender/blenkernel/intern/verse_bitmap_node.c b/source/blender/blenkernel/intern/verse_bitmap_node.c deleted file mode 100644 index 24295cd3ad0..00000000000 --- a/source/blender/blenkernel/intern/verse_bitmap_node.c +++ /dev/null @@ -1,448 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Jiri Hnidek. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" - -#include "BIF_verse.h" - -#include "BKE_verse.h" - -#include "verse.h" - -/* function prototypes of static functions */ -static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth); -static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type); -static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id); -static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile); - -static void change_layer_dimension( - VBitmapLayer *vblayer, - unsigned int old_width, - unsigned int old_height, - unsigned int t_old_width, - unsigned int t_old_height); -static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer); - -/* - * resize/crop verse bitmap layer - */ -static void change_layer_dimension( - VBitmapLayer *vblayer, - unsigned int old_width, - unsigned int old_height, - unsigned int t_old_width, - unsigned int t_old_height) -{ - struct VNode *vnode = vblayer->vnode; - unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width; - unsigned int width = ((VBitmapData*)(vnode->data))->width; - unsigned int height = ((VBitmapData*)(vnode->data))->height; - unsigned int x, y, i, j; - - i = j = 0; - - /* "copy" old data to new data */ - if(vblayer->type==VN_B_LAYER_UINT8) { - unsigned char *data = (unsigned char*)vblayer->data; - /* allocate new verse bitmap layer data */ - unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer); - for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) { - for(x=0; x<old_width && y<width; x++, i++, j++) { - new_data[i] = data[j]; - } - } - MEM_freeN(vblayer->data); - vblayer->data = new_data; - } -} - -/* - * free data stored in verse bitmap layer - */ -void free_bitmap_layer_data(VBitmapLayer *vblayer) -{ - struct VerseSession *session = vblayer->vnode->session; - - /* free name of bitmap layer */ - MEM_freeN(vblayer->name); - - /* unsubscribe from verse bitmap layer */ - if(session->flag & VERSE_CONNECTED) - verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id); - - /* free image data of bitmap layer */ - if(vblayer->data) MEM_freeN(vblayer->data); -} - -/* - * allocate data of verse bitmap layer - */ -static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer) -{ - struct VNode *vnode = vblayer->vnode; - unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width; - unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height; - unsigned int size; - void *data; - - size = t_width*t_height; - - /* allocation of own data stored in verse bitmap layer */ - switch (vblayer->type) { - case VN_B_LAYER_UINT1: - data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1"); - break; - case VN_B_LAYER_UINT8: - data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8"); - break; - case VN_B_LAYER_UINT16: - data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16"); - break; - case VN_B_LAYER_REAL32: - data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16"); - break; - case VN_B_LAYER_REAL64: - data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32"); - break; - default: - data = NULL; - break; - } - - return data; -} - -/* - * create verse bitmap layer - */ -VBitmapLayer *create_bitmap_layer( - VNode *vnode, - VLayerID layer_id, - const char *name, - VNBLayerType type) -{ - struct VBitmapLayer *vblayer; - unsigned int width = ((VBitmapData*)(vnode->data))->width; - unsigned int height = ((VBitmapData*)(vnode->data))->height; - - /* allocate memory for own verse bitmap layer */ - vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer"); - - /* verse bitmap layer will include pointer at parent verse node and own id */ - vblayer->vnode = vnode; - vblayer->id = layer_id; - - /* name of verse layer */ - vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name"); - vblayer->name[0] = '\0'; - strcpy(vblayer->name, name); - - /* type of data stored in verse bitmap layer */ - vblayer->type = type; - - /* we can allocate memory for layer data, when we know dimmension of layers; when - * we don't know it, then we will allocate this data when we will receive dimmension */ - if(width==0 || height==0) - vblayer->data = NULL; - else - vblayer->data = alloc_verse_bitmap_layer_data(vblayer); - - vblayer->flag = 0; - - return vblayer; -} - -/* - * free data of bitmap node - */ -void free_bitmap_node_data(VNode *vnode) -{ - if(vnode->data) { - struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first; - - /* free all VerseLayer data */ - while(vblayer) { - free_bitmap_layer_data(vblayer); - vblayer = vblayer->next; - } - - /* free all VerseLayers */ - BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers)); - } -} - -/* - * create data of bitmap node - */ -VBitmapData *create_bitmap_data() -{ - struct VBitmapData *vbitmap; - - vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data"); - - BLI_dlist_init(&(vbitmap->layers)); - vbitmap->queue.first = vbitmap->queue.last = NULL; - - vbitmap->width = 0; - vbitmap->height = 0; - vbitmap->depth = 0; - - vbitmap->image = NULL; - - vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set; - vbitmap->post_bitmap_layer_create = post_bitmap_layer_create; - vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy; - vbitmap->post_bitmap_tile_set = post_bitmap_tile_set; - - return vbitmap; -} - -/* - * callback function, dimension of image was changed, it is neccessary to - * crop all layers - */ -static void cb_b_dimension_set( - void *user_data, - VNodeID node_id, - uint16 width, - uint16 height, - uint16 depth) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VBitmapLayer *vblayer; - unsigned int old_width, old_height, t_old_width, t_old_height; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - -#ifdef VERSE_DEBUG_PRINT - printf("\t cb_b_dimension_set()\n"); -#endif - - /* backup old width and height */ - old_width = ((VBitmapData*)(vnode->data))->width; - old_height = ((VBitmapData*)(vnode->data))->height; - t_old_width = ((VBitmapData*)(vnode->data))->t_width; - t_old_height = ((VBitmapData*)(vnode->data))->t_height; - - /* set up new dimension of layers */ - ((VBitmapData*)(vnode->data))->width = width; - ((VBitmapData*)(vnode->data))->height = height; - ((VBitmapData*)(vnode->data))->depth = depth; - - /* we cache t_width because tiles aren't one pixel width */ - if((width % VN_B_TILE_SIZE)!=0) - ((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE; - else - ((VBitmapData*)(vnode->data))->t_width = width; - - /* we cache t_height because tiles aren't one pixel height */ - if((height % VN_B_TILE_SIZE)!=0) - ((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE; - else - ((VBitmapData*)(vnode->data))->t_height = height; - - /* crop resize all layers */ - vblayer = ((VBitmapData*)vnode->data)->layers.lb.first; - - while(vblayer) { - /* when this callback function received after cb_b_layer_create, - * then we have to allocate memory for verse bitmap layer data */ - if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer); - /* crop/resize all verse bitmap layers */ - else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height); - - vblayer = vblayer->next; - } - - /* post callback function */ - ((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode); -} - -/* - * callback function, new layer channel of image was created - */ -static void cb_b_layer_create( - void *user_data, - VNodeID node_id, - VLayerID layer_id, - const char *name, - VNBLayerType type) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VBitmapLayer *vblayer; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - -#ifdef VERSE_DEBUG_PRINT - printf("\t cb_b_layer_create()\n"); -#endif - - /* when no layer exists, then new layer will be created */ - vblayer = create_bitmap_layer(vnode, layer_id, name, type); - - /* add verse bitmap layer to list of layers */ - BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id); - - /* post callback function */ - ((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer); - -} - -/* - * callback function, existing layer of image was destroyed - */ -static void cb_b_layer_destroy( - void *user_data, - VNodeID node_id, - VLayerID layer_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VBitmapLayer *vblayer; - - if(!session) return; - - /* find node of this layer*/ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id); - if(!vblayer) return; - -#ifdef VERSE_DEBUG_PRINT - printf("\t cb_b_layer_destroy()\n"); -#endif - - /* remove verse bitmap layer from list of layers */ - BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id); - - /* post callback function */ - ((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer); - - /* free data of verse bitmap layer */ - free_bitmap_layer_data(vblayer); - - /* free verse bitmap layer */ - MEM_freeN(vblayer); -} - -/* - * callback function, small part (8x8 pixels) was changed - */ -static void cb_b_tile_set( - void *user_data, - VNodeID node_id, - VLayerID layer_id, - uint16 tile_x, - uint16 tile_y, - uint16 z, - VNBLayerType type, - const VNBTile *tile) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VBitmapLayer *vblayer; - unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j; - - if(!session) return; - - /* try to find verse node in dynamic list nodes */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - /* try to find verse bitmap layer in list of layers */ - vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id); - if(!vblayer) return; - - /* we have to have allocated memory for bitmap layer */ - if(!vblayer->data) return; - - width = ((VBitmapData*)vnode->data)->width; - height = ((VBitmapData*)vnode->data)->height; - - /* width of verse image including all tiles */ - t_height = ((VBitmapData*)vnode->data)->t_height; - /* height of verse image including all tiles */ - t_width = ((VBitmapData*)vnode->data)->t_width; - -#ifdef VERSE_DEBUG_PRINT - printf("\t cb_b_tile_set()\n"); -#endif - - xs = tile_x*VN_B_TILE_SIZE; - ys = tile_y*VN_B_TILE_SIZE; - - /* initial position in one dimension vblayer->data (y_start*width + x_start) */ - i = ys*t_width + xs; - /* intial position in one dimension tile array */ - j = 0; - - if(type==VN_B_LAYER_UINT8) { - unsigned char *data = (unsigned char*)vblayer->data; - for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs) - for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++) - data[i] = (unsigned char)tile->vuint8[j]; - } - - /* post callback function */ - ((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys); -} - -/* - * set up all callbacks functions for image nodes - */ -void set_bitmap_callbacks(void) -{ - /* dimension (size) of bitmap was set up or changes (image will be croped) */ - verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL); - - /* new layer (chanell) of image was added or created */ - verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL); - - /* existing layer was destroyed */ - verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL); - - /* some tile (small part 8x8 pixels of image was changed) */ - verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL); -} - -#endif - diff --git a/source/blender/blenkernel/intern/verse_geometry_node.c b/source/blender/blenkernel/intern/verse_geometry_node.c deleted file mode 100644 index 010e42d5cb7..00000000000 --- a/source/blender/blenkernel/intern/verse_geometry_node.c +++ /dev/null @@ -1,2098 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Jiri Hnidek. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "BKE_verse.h" -#include "BKE_utildefines.h" - -#include "BIF_verse.h" - -#include "verse.h" - -/* function prototypes of static functions */ - -/* test functions for callback functions */ -static char test_polygon_set_corner_uint32(uint32 v0, uint32 v1, uint32 v2, uint32 v3); - -/* callback functions */ -static void cb_g_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNGLayerType type, uint32 def_integer, real64 def_real); -static void cb_g_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id); -static void cb_g_vertex_set_xyz_real32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 vertex_id, real32 x, real32 y, real32 z); -static void cb_g_polygon_set_corner_uint32(void *user_data, VNodeID node_id, VLayerID layer_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3); -static void cb_g_vertex_delete_real32(void *user_data, VNodeID node_id, uint32 vertex_id); -static void cb_g_polygon_delete(void *user_data, VNodeID node_id, uint32 polygon_id); -static void cb_g_crease_set_edge(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease); -static void cb_g_crease_set_vertex(void *user_data, VNodeID node_id, const char *layer, uint32 def_crease); - -/* other static functions */ - -static void free_unneeded_verseverts_of_verseface(struct VNode *vnode, struct VerseFace *vface); -static void free_verse_vertex(struct VLayer *vlayer, struct VerseVert *vvert); -static void free_verse_face(struct VLayer *vlayer, struct VerseFace *vface); -static void free_verse_layer_data(struct VNode *vnode, struct VLayer *vlayer); - -static void send_verse_face(struct VerseFace *vface); - -static VerseVert* find_verse_vert_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 vertex_id, real32 x, real32 y, real32 z); -static VerseFace* find_verse_face_in_queue(struct VLayer *vlayer, VNodeID node_id, uint32 polygon_id, uint32 v0, uint32 v1, uint32 v2, uint32 v3); - -static unsigned short test_incoming_verseface(struct VGeomData *geom, struct VerseFace *vface); -static void find_unsent_faces(struct VNode *vnode, struct VerseVert *vvert); -static void find_vlayer_orphans(struct VNode *vnode, struct VerseVert *vvert); -static void move_face_orphan_to_dlist(struct VNode *vnode, struct VLayer *vlayer, struct VerseFace *vface); -static void increase_verse_verts_references(struct VerseFace *vface); -static void recalculate_verseface_normals(struct VNode *vnode); - -/* verse edge functions */ -static VerseEdge* find_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); -static void insert_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge); -static void remove_verse_edgehash(struct VNode *vnode, struct VerseEdge *vedge); -static void remove_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); -static void add_verse_edge(struct VNode *vnode, uint32 v0, uint32 v1); -static void update_edgehash_of_deleted_verseface(struct VNode *vnode, struct VerseFace *vface); -static void update_edgehash_of_changed_verseface(struct VNode *vnode, struct VerseFace *vface, uint32 v0, uint32 v1, uint32 v2, uint32 v3); -static void update_edgehash_of_new_verseface(struct VNode *vnode, uint32 v0, uint32 v1, uint32 v2, uint32 v3); - -/* - * recalcute normals of all VerseFaces - */ -static void recalculate_verseface_normals(VNode *vnode) -{ - struct VLayer *vert_layer, *face_layer; - struct VerseFace *vface; - struct VerseVert *vvert; - - if(vnode->type != V_NT_GEOMETRY) return; - - vert_layer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - face_layer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - - vvert = vert_layer->dl.lb.first; - while(vvert) { - vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0; - vvert = vvert->next; - } - - vface = face_layer->dl.lb.first; - while(vface) { - /* calculate face normals */ - if(vface->vvert3) { - CalcNormFloat4(vface->vvert0->co, vface->vvert1->co, - vface->vvert2->co, vface->vvert3->co, vface->no); - VecAddf(vface->vvert3->no, vface->vvert3->no, vface->no); - } - else - CalcNormFloat(vface->vvert0->co, vface->vvert1->co, - vface->vvert2->co, vface->no); - - /* calculate vertex normals ... it is averadge of all face normals using the vertex */ - VecAddf(vface->vvert0->no, vface->vvert0->no, vface->no); - VecAddf(vface->vvert1->no, vface->vvert1->no, vface->no); - VecAddf(vface->vvert2->no, vface->vvert2->no, vface->no); - - vface = vface->next; - } - - /* we have to normalize all vertex normals */ - vvert = vert_layer->dl.lb.first; - while(vvert) { - Normalize(vvert->no); - vvert = vvert->next; - } -} - -/* - * add created item to the queue and send it if possible - */ -void add_item_to_send_queue(ListBase *lb, void *item, short type) -{ - struct VNode *vnode; - struct VLayer *vlayer; - struct VerseVert *vvert; - struct VerseFace *vface; - - /* this prevent from adding duplicated faces */ - if(type==VERSE_FACE) { - struct Link *link = (Link*)lb->first; - while(link) { - if(link==item) { - if(((VerseFace*)item)->flag & FACE_SENT) { -/* printf("\tverse face %d marked as OBSOLETE\n", ((VerseFace*)item)->id);*/ - ((VerseFace*)item)->flag |= FACE_OBSOLETE; - } - return; - } - link = link->next; - } - } - - /* add item to sending queue (two way dynamic list) */ - BLI_addtail(lb, item); - - /* send item, when it is possible */ - switch (type) { - case VERSE_NODE: /* only first node in queue can be sent */ - if(lb->first==lb->last) - send_verse_node((VNode*)item); - break; - case VERSE_LINK: /* both object between have to exist */ - if(((VLink*)item)->flag & LINK_SEND_READY) - send_verse_link((VLink*)item); - break; - case VERSE_LAYER: - if(((VLayer*)item)->vnode->flag & NODE_RECEIVED) - send_verse_layer((VLayer*)item); - break; - case VERSE_VERT: - if(((VerseVert*)item)->vlayer->flag & LAYER_RECEIVED) - send_verse_vertex((VerseVert*)item); - break; - case VERSE_FACE: /* all vertexes of face have to be received */ - if(((VerseFace*)item)->flag & FACE_SEND_READY) - send_verse_face((VerseFace*)item); - break; - case VERSE_TAG: - send_verse_tag((VTag*)item); - break; - case VERSE_TAG_GROUP: - send_verse_taggroup((VTagGroup*)item); - break; - case VERSE_VERT_UINT32: /* parent item has to exist */ - vnode = (((uint32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); - vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id ); - if(vvert != NULL) - send_verse_vert_uint32((uint32_item*)item, type); - break; - case VERSE_VERT_REAL32: /* parent item has to exist */ - vnode = (((real32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); - vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id ); - if( vvert != NULL) - send_verse_vert_real32((real32_item*)item, type); - break; - case VERSE_VERT_VEC_REAL32: /* parent item has to exist */ - vnode = (((vec_real32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 0 ); - vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), ((vec_real32_item*)item)->id ); - if(vvert != NULL) - send_verse_vert_vec_real32((vec_real32_item*)item, type); - break; - case VERSE_FACE_UINT8: /* parent item has to exist */ - vnode = (((uint8_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint8_item*)item)->id ); - if(vface != NULL) - send_verse_face_uint8((uint8_item*)item, type); - break; - case VERSE_FACE_UINT32: /* parent item has to exist */ - vnode = (((uint32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((uint32_item*)item)->id ); - if(vface != NULL) - send_verse_face_uint32((uint32_item*)item, type); - break; - case VERSE_FACE_REAL32: /* parent item has to exist */ - vnode = (((real32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((real32_item*)item)->id ); - if(vface != NULL) - send_verse_face_real32((real32_item*)item, type); - break; - case VERSE_FACE_QUAT_UINT32: /* parent item has to exist */ - vnode = (((quat_uint32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_uint32_item*)item)->id ); - if(vface != NULL) - send_verse_face_corner_quat_uint32((quat_uint32_item*)item, type); - break; - case VERSE_FACE_QUAT_REAL32: /* parent item has to exist */ - vnode = (((quat_real32_item*)item)->vlayer)->vnode; - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), 1 ); - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), ((quat_real32_item*)item)->id ); - if(vface != NULL) - send_verse_face_corner_quat_real32((quat_real32_item*)item, type); - break; - } -} - -/* - * return VerseLayer with certain content (vertexes, polygons, in the - * future: weight, red color, etc.) - */ -VLayer* find_verse_layer_type(VGeomData *geom, short content) -{ - struct VLayer *vlayer = NULL; - - switch(content) { - case VERTEX_LAYER: - /* VERTEX_LAYER equals 0 and vertex layer is - * always in 1st layer */ - vlayer = geom->layers.da.items[VERTEX_LAYER]; - break; - case POLYGON_LAYER: - /* POLYGON_LAYER equals 1 and vertex layer is - * always in 2nd layer */ - vlayer = geom->layers.da.items[POLYGON_LAYER]; - break; - } - - return vlayer; -} - -/* - * increase references of VerseVerts of new VerseFace - */ -static void increase_verse_verts_references(VerseFace *vface) -{ - if(vface->vvert0) vface->vvert0->counter++; - if(vface->vvert1) vface->vvert1->counter++; - if(vface->vvert2) vface->vvert2->counter++; - if(vface->vvert3) vface->vvert3->counter++; -} - -/* - * move VerseFace from list of orphans to dlist of VerseFaces (if VerseFace was only changed - * then this VerseFace is only removed from list of orphans) - */ -static void move_face_orphan_to_dlist(VNode *vnode, VLayer *vlayer, VerseFace *vface) -{ - /* remove vface from list of orphans */ - BLI_remlink(&(vlayer->orphans), vface); - /* increase references of all vertexes beying part of this face*/ - increase_verse_verts_references(vface); - - if(vface->flag & FACE_RECEIVED) { - /* set up vface flag */ - vface->flag &= ~FACE_RECEIVED; - /* move vface to dynamic list of faces */ - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id); - /* recalculate all vertex and faces normals */ - recalculate_verseface_normals(vnode); - /* post create action (change local data) */ - ((VGeomData*)vnode->data)->post_polygon_create(vface); - } - else if(vface->flag & FACE_CHANGED) { - /* set up vface flag */ - vface->flag &= ~FACE_CHANGED; - /* move vface to dynamic list of faces */ - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, vface->id); - /* recalculate all vertex and faces normals */ - recalculate_verseface_normals(vnode); - /* post create action (change local data) */ - ((VGeomData*)vnode->data)->post_polygon_set_corner(vface); - } -} - -/* - * find all VerseFaces waiting in queue, which needs id of new VerseVert - */ -static void find_unsent_faces(VNode *vnode, VerseVert *vvert) -{ - VLayer *vlayer; - VerseFace *vface, *next_vface; - - vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - - if(vlayer) { - vface = vlayer->queue.first; - while(vface) { - next_vface = vface->next; - if(vface->vvert0==vvert) { - vface->v0 = vvert->id; - vface->counter--; - } - else if(vface->vvert1==vvert) { - vface->v1 = vvert->id; - vface->counter--; - } - else if(vface->vvert2==vvert) { - vface->v2 = vvert->id; - vface->counter--; - } - else if(vface->vvert3==vvert){ - vface->v3 = vvert->id; - vface->counter--; - } - - if(vface->counter<1 && !(vface->flag & FACE_SENT)) - send_verse_face(vface); - - vface = next_vface; - } - } -} - -/* - * find all VerseFace orphans, which needs incoming VerseVert - */ -static void find_vlayer_orphans(VNode *vnode, VerseVert *vvert) -{ - VLayer *vlayer; - VerseFace *vface, *next_vface; - unsigned int vertex_id = vvert->id; - - vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - - if(vlayer) { - vface = vlayer->orphans.first; - while(vface){ - next_vface = vface->next; - if(vface->v0 == vertex_id) { - vface->vvert0 = vvert; - vface->counter--; - } - else if(vface->v1 == vertex_id) { - vface->vvert1 = vvert; - vface->counter--; - } - else if(vface->v2 == vertex_id) { - vface->vvert2 = vvert; - vface->counter--; - } - else if(vface->v3 == vertex_id) { - vface->vvert3 = vvert; - vface->counter--; - } - if(vface->counter<1) { - /* moving VerseFace orphan to dlist */ - move_face_orphan_to_dlist(vnode, vlayer, vface); - } - vface = next_vface; - } - } -} - -/* - * return number of VerseVerts missing to incoming VerseFace, set up pointers - * at VerseVerts - */ -static unsigned short test_incoming_verseface(VGeomData *geom, VerseFace *vface) -{ - struct VLayer *vert_layer; - struct VerseVert *vvert; - int counter=0; - - vert_layer = find_verse_layer_type(geom, VERTEX_LAYER); - - if(vface->v0 != -1){ - vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v0); - if(vvert==NULL) counter++; - else vface->vvert0 = vvert; - } - if(vface->v1 != -1){ - vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v1); - if(vvert==NULL) counter++; - else vface->vvert1 = vvert; - } - if(vface->v2 != -1){ - vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v2); - if(vvert==NULL) counter++; - else vface->vvert2 = vvert; - } - if(vface->v3 != -1){ - vvert = BLI_dlist_find_link(&(vert_layer->dl), vface->v3); - if(vvert==NULL) counter++; - else vface->vvert3 = vvert; - } - - return counter; -} - -/* - * try to find changed VerseFace in sending queue - */ -static VerseFace* find_changed_verse_face_in_queue(VLayer *vlayer, uint32 polygon_id) -{ - struct VerseFace *vface = vlayer->queue.first; - - while(vface){ - if(vface->id == polygon_id && vface->flag & FACE_CHANGED) { - return vface; - } - vface = vface->next; - } - return NULL; -} - -/* - * try to find VerseFace in queue - */ -static VerseFace* find_verse_face_in_queue( - VLayer *vlayer, - VNodeID node_id, - uint32 polygon_id, - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - struct VerseFace *vface = vlayer->queue.first; - - while(vface){ - if((vface->v0==v0) && (vface->v1==v1) && (vface->v2==v2) && (vface->v3==v3)){ - vface->id = polygon_id; - vface->vlayer = vlayer; - return vface; - } - vface = vface->next; - } - return NULL; -} - -/* - * try to find VerseVert in queue - */ -static VerseVert* find_verse_vert_in_queue( - VLayer *vlayer, - VNodeID node_id, - uint32 vertex_id, - real32 x, - real32 y, - real32 z) -{ - struct VerseVert *vvert = vlayer->queue.first; - - while(vvert){ - if((vvert->vlayer->vnode->id == node_id) && (vvert->co[0] == x) && (vvert->co[1] == y) && (vvert->co[2] == z)) - { - vvert->id = vertex_id; - vvert->vlayer = vlayer; - - return vvert; - } - vvert = vvert->next; - } - - return NULL; -} - - -/* - * send quat of float values to verse server (4x32 bits) - */ -void send_verse_face_corner_quat_real32(quat_real32_item *item, short type) -{ - verse_send_g_polygon_set_corner_real32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value[0], - item->value[1], - item->value[2], - item->value[3]); -} - -/* - * send quat of unsigned int values to verse server (4x32 bits) - */ -void send_verse_face_corner_quat_uint32(quat_uint32_item *item, short type) -{ - verse_send_g_polygon_set_corner_uint32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value[0], - item->value[1], - item->value[2], - item->value[3]); -} - -/* - * send float value (32 bits) to verse server - */ -void send_verse_face_real32(real32_item *item, short type) -{ - verse_send_g_polygon_set_face_real32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value); -} - -/* - * send unsigned integer (32 bits) to verse server - */ -void send_verse_face_uint32(uint32_item *item, short type) -{ - verse_send_g_polygon_set_face_uint32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value); -} - -/* - * send unsigned char (8 bits) to verse server - */ -void send_verse_face_uint8(uint8_item *item, short type) -{ - verse_send_g_polygon_set_face_uint8( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value); -} - -/* - * send vector of float values to verse server (3x32 bits) - */ -void send_verse_vert_vec_real32(vec_real32_item *item, short type) -{ - verse_send_g_vertex_set_xyz_real32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value[0], - item->value[1], - item->value[2]); -} - -/* - * send float value (32 bits) to verse server - */ -void send_verse_vert_real32(real32_item *item, short type) -{ - verse_send_g_vertex_set_real32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value); -} - -/* - * send unsigned integer (32 bits) to verse server - */ -void send_verse_vert_uint32(uint32_item *item, short type) -{ - verse_send_g_vertex_set_uint32( - item->vlayer->vnode->id, - item->vlayer->id, - item->id, - item->value); -} - -/* - * send delete command to verse server - */ -void send_verse_vertex_delete(VerseVert *vvert) -{ - verse_session_set(vvert->vlayer->vnode->session->vsession); - - vvert->flag |= VERT_OBSOLETE; - - verse_send_g_vertex_delete_real32(vvert->vlayer->vnode->id, vvert->id); -} - -/* - * send VerseLayer to verse server - */ -void send_verse_layer(VLayer *vlayer) -{ - verse_session_set(vlayer->vnode->session->vsession); - - verse_send_g_layer_create( - vlayer->vnode->id, - vlayer->id, - vlayer->name, - vlayer->type, - vlayer->def_int, - vlayer->def_real); -} - -/* - * send VerseVert to verse server - */ -void send_verse_vertex(VerseVert *vvert) -{ - /* new vertex position will not be sent, when vertex was deleted */ - if(vvert->flag & VERT_OBSOLETE) return; - - verse_session_set(vvert->vlayer->vnode->session->vsession); - - verse_send_g_vertex_set_xyz_real32( - vvert->vlayer->vnode->id, - vvert->vlayer->id, - vvert->id, - vvert->co[0], - vvert->co[2], - -vvert->co[1]); -} - -/* - * send delete command to verse server - */ -void send_verse_face_delete(VerseFace *vface) -{ - verse_session_set(vface->vlayer->vnode->session->vsession); - - vface->flag |= FACE_DELETED; - - verse_send_g_polygon_delete(vface->vlayer->vnode->id, vface->id); -} - -/* - * send VerseFace to verse server - */ -static void send_verse_face(VerseFace *vface) -{ - verse_session_set(vface->vlayer->vnode->session->vsession); - - vface->flag |= FACE_SENT; - - if(vface->v3 != -1) { - verse_send_g_polygon_set_corner_uint32( - vface->vlayer->vnode->id, - vface->vlayer->id, - vface->id, - vface->v0, - vface->v3, /* verse use clock-wise winding */ - vface->v2, - vface->v1); /* verse use clock-wise winding */ - } - else { - verse_send_g_polygon_set_corner_uint32( - vface->vlayer->vnode->id, - vface->vlayer->id, - vface->id, - vface->v0, - vface->v2, /* verse use clock-wise winding */ - vface->v1, /* verse use clock-wise winding */ - vface->v3); - } -} - -/* - * free VerseVert - */ -static void free_verse_vertex(VLayer *vlayer, VerseVert *vvert) -{ - /* free VerseVert */ - BLI_freelinkN(&(vlayer->orphans), vvert); -} - -/* - * free VerseFace (and blender face) - */ -static void free_verse_face(VLayer *vlayer, VerseFace *vface) -{ - /* free VerseFace */ - BLI_dlist_free_item(&(vlayer->dl), (unsigned int)vface->id); -} - -/* - * free VerseLayer data - */ -static void free_verse_layer_data(VNode *vnode, VLayer *vlayer) -{ - struct VerseFace *vface; - struct VerseVert *vvert; - - /* set up EditVert->vvert and EditFace->vface pointers to NULL */ - switch(vlayer->content) { - case VERTEX_LAYER: - vvert = (VerseVert*)vlayer->dl.lb.first; - while(vvert) { - ((VGeomData*)vnode->data)->post_vertex_free_constraint(vvert); - vvert = vvert->next; - } - break; - case POLYGON_LAYER: - vface = (VerseFace*)vlayer->dl.lb.first; - while(vface) { - ((VGeomData*)vnode->data)->post_polygon_free_constraint(vface); - vface = vface->next; - } - break; - default: - break; - } - /* free Verse Layer name */ - MEM_freeN(vlayer->name); - /* destroy VerseLayer data (vertexes, polygons, etc.) */ - BLI_dlist_destroy(&(vlayer->dl)); - /* free unsent data */ - BLI_freelistN(&(vlayer->queue)); - /* free orphans */ - BLI_freelistN(&(vlayer->orphans)); -} - -/* - * free all unneeded VerseVerts waiting for deleting - */ -static void free_unneeded_verseverts_of_verseface(VNode *vnode, VerseFace *vface) -{ - struct VLayer *vert_vlayer; - - /* find layer containing vertexes */ - vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - - /* free all "deleted" VerseVert waiting for deleting this VerseFace */ - - if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0); - free_verse_vertex(vert_vlayer, vface->vvert0); - vface->vvert0 = NULL; - } - if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1); - free_verse_vertex(vert_vlayer, vface->vvert1); - vface->vvert1 = NULL; - } - if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2); - free_verse_vertex(vert_vlayer, vface->vvert2); - vface->vvert2 = NULL; - } - if((vface->vvert3) && (vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3); - free_verse_vertex(vert_vlayer, vface->vvert3); - vface->vvert3 = NULL; - } -} - -/* - * This function create VerseVert and returns pointer on this vertex - */ -VerseVert* create_verse_vertex( - VLayer *vlayer, - uint32 vertex_id, - real32 x, - real32 y, - real32 z) -{ - struct VerseVert *vvert; - - vvert = (VerseVert*)MEM_mallocN(sizeof(VerseVert), "VerseVert"); - - /* set up pointer on parent node */ - vvert->vlayer = vlayer; - vvert->id = vertex_id; - /* position */ - vvert->co[0] = x; - vvert->co[1] = y; - vvert->co[2] = z; - /* normal */ - vvert->no[0] = vvert->no[1] = vvert->no[2] = 0.0; - /* blender internals */ - vvert->flag = 0; - vvert->counter = 0; - vvert->vertex = NULL; - - /* increase layer counter of vertexes */ - vlayer->counter++; - - return vvert; -} - -/* - * this function creates fake VerseEdge and returns pointer at this edge - */ -VerseEdge *create_verse_edge(uint32 v0, uint32 v1) -{ - struct VerseEdge *vedge; - - vedge = (VerseEdge*)MEM_mallocN(sizeof(VerseEdge), "VerseEdge"); - - vedge->v0 = v0; - vedge->v1 = v1; - vedge->counter = 0; - - return vedge; -} - -/* - * this function will create new VerseFace and will return pointer on such Face - */ -VerseFace* create_verse_face( - VLayer *vlayer, - uint32 polygon_id, - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - struct VerseFace *vface; - - vface = (VerseFace*)MEM_mallocN(sizeof(VerseFace), "VerseFace"); - - /* verse data */ - vface->vlayer = vlayer; - vface->id = polygon_id; - - vface->vvert0 = NULL; - vface->vvert1 = NULL; - vface->vvert2 = NULL; - vface->vvert3 = NULL; - - vface->v0 = v0; - vface->v1 = v1; - vface->v2 = v2; - vface->v3 = v3; - - /* blender data */ - vface->face = NULL; - vface->flag = 0; - vface->counter = 4; - - /* increase layer counter of faces */ - vlayer->counter++; - - return vface; -} - -/* - * create and return VerseLayer - */ -VLayer *create_verse_layer( - VNode *vnode, - VLayerID layer_id, - const char *name, - VNGLayerType type, - uint32 def_integer, - real64 def_real) -{ - struct VLayer *vlayer; - - /* add layer to the DynamicList */ - vlayer = (VLayer*)MEM_mallocN(sizeof(VLayer), "VerseLayer"); - - /* store all relevant info to the vlayer and set up vlayer */ - vlayer->vnode = vnode; - vlayer->id = layer_id; - vlayer->name = (char*)MEM_mallocN(sizeof(char)*(sizeof(name)+1),"Verse Layer name"); - strcpy(vlayer->name, name); - vlayer->type = type; - vlayer->def_int = def_integer; - vlayer->def_real = def_real; - - if((type == VN_G_LAYER_VERTEX_XYZ) && (layer_id == 0)) - vlayer->content = VERTEX_LAYER; - else if((type == VN_G_LAYER_POLYGON_CORNER_UINT32) && (layer_id == 1)) - vlayer->content = POLYGON_LAYER; - else - vlayer->content = -1; - - /* initialize DynamicList in the vlayer (vertexes, polygons, etc.)*/ - BLI_dlist_init(&(vlayer->dl)); - /* initialization of queue of layer */ - vlayer->queue.first = vlayer->queue.last = NULL; - /* initialization of list of orphans */ - vlayer->orphans.first = vlayer->orphans.last = NULL; - /* initialize number of sent items (vertexes, faces, etc) */ - vlayer->counter = 0; - /* initialize flag */ - vlayer->flag = 0; - - /* set up methods */ - vlayer->post_layer_create = post_layer_create; - vlayer->post_layer_destroy = post_layer_destroy; - - return vlayer; -} - -/* - * create geometry data - */ -VGeomData *create_geometry_data(void) -{ - struct VGeomData *geom; - - geom = (VGeomData*)MEM_mallocN(sizeof(VGeomData), "VerseGeometryData"); - BLI_dlist_init(&(geom->layers)); - geom->vlink = NULL; - geom->queue.first = geom->queue.last = NULL; - geom->mesh = NULL; - geom->editmesh = NULL; - - /* initialize list of fake verse edges and initialize verse edge hash */ - geom->edges.first = geom->edges.last = NULL; - geom->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); - - /* set up methods */ - geom->post_vertex_create = post_vertex_create; - geom->post_vertex_set_xyz = post_vertex_set_xyz; - geom->post_vertex_delete = post_vertex_delete; - geom->post_vertex_free_constraint = post_vertex_free_constraint; - geom->post_polygon_create = post_polygon_create; - geom->post_polygon_set_corner = post_polygon_set_corner; - geom->post_polygon_delete = post_polygon_delete; - geom->post_polygon_free_constraint = post_polygon_free_constraint; - geom->post_geometry_free_constraint = post_geometry_free_constraint; - geom->post_polygon_set_uint8 = post_polygon_set_uint8; - - return geom; -} - -/* Create item containing 4 floats */ -static quat_real32_item *create_quat_real32_item( - VLayer *vlayer, - uint32 item_id, - real32 v0, - real32 v1, - real32 v2, - real32 v3) -{ - struct quat_real32_item *item; - - item = (quat_real32_item*)MEM_mallocN(sizeof(quat_real32_item), "quat_real32_item"); - - item->vlayer = vlayer; - item->id = item_id; - item->value[0] = v0; - item->value[1] = v1; - item->value[2] = v2; - item->value[3] = v3; - - return item; -} - -/* Create item containing 1 float */ -static real32_item *create_real32_item(VLayer *vlayer, uint32 item_id, real32 value) -{ - struct real32_item *item; - - item = (real32_item*)MEM_mallocN(sizeof(real32_item), "real32_item"); - - item->vlayer = vlayer; - item->id = item_id; - item->value = value; - - return item; -} - -/* Create item containing 1 integer */ -static uint32_item *create_uint32_item(VLayer *vlayer, uint32 item_id, uint32 value) -{ - struct uint32_item *item; - - item = (uint32_item*)MEM_mallocN(sizeof(uint32_item), "uint32_item"); - - item->vlayer = vlayer; - item->id = item_id; - item->value = value; - - return item; -} - -/* Create item containing 1 byte */ -static uint8_item *create_uint8_item(VLayer *vlayer, uint32 item_id, uint8 value) -{ - struct uint8_item *item; - - item = (uint8_item*)MEM_mallocN(sizeof(uint8_item), "uint8_item"); - - item->vlayer = vlayer; - item->id = item_id; - item->value = value; - - return item; -} - -/* - * callback function: vertex crease was set - */ -static void cb_g_crease_set_vertex( - void *user_data, - VNodeID node_id, - const char *layer, - uint32 def_crease) -{ -} - -/* - * we have to test corretness of incoming data from verse server - * no two vertexes can have the same index - */ -static char test_polygon_set_corner_uint32( - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - if((v0==v1) || (v0==v2) || (v0==v3) || (v1==v2) || (v1==v3) || (v2==v3)) - return 0; - else - return 1; -} - -/* - * try to find verse layer in sending queue of verse geometry node - */ -static VLayer *find_vlayer_in_sending_queue(VNode *vnode, VLayerID layer_id) -{ - struct VLayer *vlayer; - - /* try to find verse layyer in sending queue */ - vlayer = ((VGeomData*)vnode->data)->queue.first; - while(vlayer) { - if(vlayer->id==layer_id) return vlayer; - vlayer = vlayer->next; - } - - return NULL; -} - -/* - * this function will find edge in hash table, hash function isn't too optimal (it needs - * lot of memory for every verse node), but it works without any bug - */ -static VerseEdge* find_verse_edge(VNode *vnode, uint32 v0, uint32 v1) -{ - struct HashVerseEdge *hve; - - if(((VGeomData*)vnode->data)->hash==NULL) - ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); - - hve = ((VGeomData*)vnode->data)->hash + VEDHASH(v0, v1);; - while(hve) { - /* edge v0---v1 is the same edge as v1---v0 */ - if(hve->vedge && ((hve->vedge->v0==v0 && hve->vedge->v1==v1) || (hve->vedge->v0==v1 && hve->vedge->v1==v0))) return hve->vedge; - hve = hve->next; - } - - return NULL; -} - -/* - * insert hash of verse edge to hash table - */ -static void insert_verse_edgehash(VNode *vnode, VerseEdge *vedge) -{ - struct HashVerseEdge *first, *hve; - - if(((VGeomData*)vnode->data)->hash==NULL) - ((VGeomData*)vnode->data)->hash = MEM_callocN(VEDHASHSIZE*sizeof(HashVerseEdge), "verse hashedge tab"); - - first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1); - - if(first->vedge==NULL) { - first->vedge = vedge; - } - else { - hve = &(vedge->hash); - hve->vedge = vedge; - hve->next = first->next; - first->next = hve; - } -} - -/* - * remove hash of verse edge from hash table - */ -static void remove_verse_edgehash(VNode *vnode, VerseEdge *vedge) -{ - struct HashVerseEdge *first, *hve, *prev; - - hve = first = ((VGeomData*)vnode->data)->hash + VEDHASH(vedge->v0, vedge->v1); - - while(hve) { - if(hve->vedge == vedge) { - if(hve==first) { - if(first->next) { - hve = first->next; - first->vedge = hve->vedge; - first->next = hve->next; - } - else { - hve->vedge = NULL; - } - } - else { - prev->next = hve->next; - } - return; - } - prev = hve; - hve = hve->next; - } -} - -/* - * this function will try to remove existing fake verse edge, when this verse - * edge is still used by some faces, then counter will be only decremented - */ -static void remove_verse_edge(VNode *vnode, uint32 v0, uint32 v1) -{ - struct VerseEdge *vedge; - - vedge = find_verse_edge(vnode, v0, v1); - if(vedge) { - vedge->counter--; - if(vedge->counter==0) { - remove_verse_edgehash(vnode, vedge); - BLI_freelinkN(&(((VGeomData*)vnode->data)->edges), vedge); - } - } - else { - printf("error: remove_verse_edge %d, %d\n", v0, v1); - } -} - -/* - * this function will try to add new fake verse edge, when no such edge exist, - * when such edge exist, then only counter of edge will be incremented - */ -static void add_verse_edge(VNode *vnode, uint32 v0, uint32 v1) -{ - struct VerseEdge *vedge; - - vedge = find_verse_edge(vnode, v0, v1); - if(!vedge) { - if(v0!=v1) { - vedge = create_verse_edge(v0, v1); - BLI_addtail(&(((VGeomData*)vnode->data)->edges), vedge); - insert_verse_edgehash(vnode, vedge); - } - else { - printf("error:add_verse_edge: %d, %d\n", v0, v1); - return; - } - } - vedge->counter++; -} - -/* - * verse face was deleted ... update edge hash - */ -static void update_edgehash_of_deleted_verseface(VNode *vnode, VerseFace *vface) -{ - uint32 v0, v1, v2, v3; /* verse vertex indexes of deleted verse face */ - - v0 = vface->vvert0->id; - v1 = vface->vvert1->id; - v2 = vface->vvert2->id; - v3 = vface->vvert3 ? vface->vvert3->id : -1; - - remove_verse_edge(vnode, v0, v1); - remove_verse_edge(vnode, v1, v2); - if(v3!=-1) { - remove_verse_edge(vnode, v2, v3); - remove_verse_edge(vnode, v3, v0); - } - else { - remove_verse_edge(vnode, v2, v0); - } -} - -/* - * existing verse face was changed ... update edge hash - */ -static void update_edgehash_of_changed_verseface( - VNode *vnode, - VerseFace *vface, - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - uint32 ov0, ov1, ov2, ov3; /* old indexes at verse vertexes*/ - - ov0 = vface->vvert0->id; - ov1 = vface->vvert1->id; - ov2 = vface->vvert2->id; - ov3 = vface->vvert3 ? vface->vvert3->id : -1; - - /* 1st edge */ - if(v0!=ov0 || v1!=ov1) { - remove_verse_edge(vnode, ov0, ov1); - add_verse_edge(vnode, v0, v1); - } - - /* 2nd edge */ - if(v1!=ov1 || v2!=ov2) { - remove_verse_edge(vnode, ov1, ov2); - add_verse_edge(vnode, v1, v2); - } - - /* 3rd edge */ - if(v2!=ov2 || v3!=ov3 || v0!=ov0) { - if(ov3!=-1) { - remove_verse_edge(vnode, ov2, ov3); - if(v3!=-1) { - add_verse_edge(vnode, v2, v3); /* new 3rd edge (quat->quat) */ - } - else { - remove_verse_edge(vnode, ov3, ov0); /* old edge v3,v0 of quat have to be removed */ - add_verse_edge(vnode, v2, v0); /* new 3rd edge (quat->triangle) */ - } - } - else { - remove_verse_edge(vnode, ov2, ov0); - if(v3!=-1) { - add_verse_edge(vnode, v2, v3); /* new 3rd edge (triangle->quat) */ - } - else { - add_verse_edge(vnode, v2, v0); /* new 3rd edge (triangle->triangle) */ - } - } - } - - /* 4th edge */ - if(v3!=-1 && (v3!=ov3 || v0!=ov0)) { - remove_verse_edge(vnode, ov3, ov0); - add_verse_edge(vnode, v3, v0); - } -} - -/* - * new verse face was created ... update list of edges and edge has - */ -static void update_edgehash_of_new_verseface( - VNode *vnode, - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - /* when edge already exists, then only its counter is incremented, - * look at commentary of add_verse_edge() function */ - add_verse_edge(vnode, v0, v1); - add_verse_edge(vnode, v1, v2); - if(v3!=-1) { - add_verse_edge(vnode, v2, v3); - add_verse_edge(vnode, v3, v0); - } - else { - add_verse_edge(vnode, v2, v0); - } -} - -/* - * callback function: edge crease was set - */ -static void cb_g_crease_set_edge( - void *user_data, - VNodeID node_id, - const char *layer, - uint32 def_crease) -{ -} - -/* - * callback function: float value for polygon was set up - */ -static void cb_g_polygon_set_face_real32( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 polygon_id, - real32 value) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct real32_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); - - if(item) { - item->value = value; - } - else { - item = create_real32_item(vlayer, polygon_id, value); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: int values for polygon was set up - */ -static void cb_g_polygon_set_face_uint32( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 polygon_id, - uint32 value) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct uint32_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); - - if(item) { - item->value = value; - } - else { - item = create_uint32_item(vlayer, polygon_id, value); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: uint8 value for polygon was set up - */ -static void cb_g_polygon_set_face_uint8( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 polygon_id, - uint8 value) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct uint8_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); - - if(item) { - item->value = value; - } - else { - item = create_uint8_item(vlayer, polygon_id, value); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: float value for polygon corner was set up - */ -static void cb_g_polygon_set_corner_real32( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 polygon_id, - real32 v0, - real32 v1, - real32 v2, - real32 v3) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct quat_real32_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), polygon_id); - - if(item) { - item->value[0] = v0; - item->value[1] = v1; - item->value[2] = v2; - item->value[3] = v3; - } - else { - item = create_quat_real32_item(vlayer, polygon_id, v0, v1, v2, v3); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: polygon is deleted - */ -static void cb_g_polygon_delete( - void *user_data, - VNodeID node_id, - uint32 polygon_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - VNode *vnode; - VLayer *vlayer; - VerseFace *vface; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = BLI_dlist_find_link(&(session->nodes), node_id); - - /* find layer containing faces */ - vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - - /* find wanted VerseFace */ - vface = BLI_dlist_find_link(&(vlayer->dl), polygon_id); - - if(!vface) return; - - /* update edge hash */ - update_edgehash_of_deleted_verseface(vnode, vface); - - ((VGeomData*)vnode->data)->post_polygon_delete(vface); - - /* decrease references at coresponding VerseVertexes */ - vface->vvert0->counter--; - vface->vvert1->counter--; - vface->vvert2->counter--; - if(vface->vvert3) vface->vvert3->counter--; - - /* delete unneeded VerseVertexes */ - free_unneeded_verseverts_of_verseface(vnode, vface); - - free_verse_face(vlayer, vface); -} - -/* - * callback function: new polygon (face) created or existing polygon was changed - */ -static void cb_g_polygon_set_corner_uint32( - void *user_data, - VNodeID node_id, - VLayerID layer_id, - uint32 polygon_id, - uint32 v0, - uint32 v1, - uint32 v2, - uint32 v3) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct VerseFace *vface=NULL; - - if(!session) return; - - /* try to find VerseNode */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - /* try to find VerseLayer */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - if(!vlayer) return; - - /* we have to test coretness of incoming data */ - if(!test_polygon_set_corner_uint32(v0, v1, v2, v3)) return; - - /* Blender uses different order of vertexes */ - if(v3!=-1) { /* quat swap */ - unsigned int v; v = v1; v1 = v3; v3 = v; - } - else { /* triangle swap */ - unsigned int v; v = v1; v1 = v2; v2 = v; - } - - /* try to find VerseFace */ - vface = (VerseFace*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)polygon_id); - - /* try to find modified VerseFace */ - if(!vface) { - vface = find_changed_verse_face_in_queue(vlayer, polygon_id); - if(vface) { - BLI_remlink(&(vlayer->queue), (void*)vface); - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id); - } - } - - if(!vface) { - /* try to find VerseFace in list of VerseVaces created by me and set up polygon and - * layer ids */ - vface = find_verse_face_in_queue(vlayer, node_id, polygon_id, v0, v1, v2, v3); - - /* update edge hash */ - update_edgehash_of_new_verseface(vnode, v0, v1, v2, v3); - - if(vface){ - /* I creeated this face ... remove VerseFace from queue */ - BLI_remlink(&(vlayer->queue), (void*)vface); - } - else { - /* some other client created this face*/ - vface = create_verse_face(vlayer, polygon_id, v0, v1, v2, v3); - } - - vface->flag &= ~FACE_SENT; - - /* return number of missing verse vertexes */ - vface->counter = test_incoming_verseface((VGeomData*)vnode->data, vface); - - if(vface->counter < 1) { - /* when VerseFace received all needed VerseFaces, then it is moved - * to list of VerseFaces */ - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vface, (unsigned int)polygon_id); - increase_verse_verts_references(vface); - recalculate_verseface_normals(vnode); - ((VGeomData*)vnode->data)->post_polygon_create(vface); - } - else { - /* when all needed VerseVertexes weren't received, then VerseFace is moved to - * the list of orphans waiting on needed vertexes */ - vface->flag |= FACE_RECEIVED; - BLI_addtail(&(vlayer->orphans), (void*)vface); - } - } - else { - VLayer *vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - /* VerseVertexes of existing VerseFace were changed (VerseFace will use some different - * VerseVertexes or it will use them in different order) */ - - /* update fake verse edges */ - update_edgehash_of_changed_verseface(vnode, vface, v0, v1, v2, v3); - - /* initialize count of unreceived vertexes needed for this face */ - vface->counter = 4; - - /* 1st corner */ - if(vface->vvert0->id != v0) { - /* decrease references of obsolete vertexes*/ - vface->vvert0->counter--; - /* delete this vertex, when it isn't used by any face and it was marked as deleted */ - if((vface->vvert0->counter < 1) && (vface->vvert0->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert0); - free_verse_vertex(vert_vlayer, vface->vvert0); - } - /* try to set up new pointer at verse vertex */ - vface->v0 = v0; - vface->vvert0 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v0); - if(vface->vvert0) { - /* increase references at new vertex */ - vface->vvert0->counter++; - /* decrease count of needed vertex to receive */ - vface->counter--; - } - - } - else - /* this corner wasn't changed */ - vface->counter--; - - /* 2nd corner */ - if(vface->vvert1->id != v1) { - vface->vvert1->counter--; - if((vface->vvert1->counter < 1) && (vface->vvert1->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert1); - free_verse_vertex(vert_vlayer, vface->vvert1); - } - vface->v1 = v1; - vface->vvert1 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v1); - if(vface->vvert1) { - vface->vvert1->counter++; - vface->counter--; - } - } - else - vface->counter--; - - /* 3rd corner */ - if(vface->vvert2->id != v2) { - vface->vvert2->counter--; - if((vface->vvert2->counter < 1) && (vface->vvert2->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert2); - free_verse_vertex(vert_vlayer, vface->vvert2); - } - vface->v2 = v2; - vface->vvert2 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v2); - if(vface->vvert2) { - vface->vvert2->counter++; - vface->counter--; - } - } - else - vface->counter--; - - /* 4th corner */ - if(vface->vvert3) { - if(vface->vvert3->id != v3) { - vface->vvert3->counter--; - if((vface->vvert3->counter < 1) && (vface->vvert3->flag & VERT_DELETED)) { - ((VGeomData*)vnode->data)->post_vertex_delete(vface->vvert3); - free_verse_vertex(vert_vlayer, vface->vvert3); - } - vface->v3 = v3; - if(v3 != -1) { - vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3); - if(vface->vvert3) { - vface->vvert3->counter++; - vface->counter--; - } - } - else { - /* this is some special case, this face hase now only 3 corners - * quat -> triangle */ - vface->vvert3 = NULL; - vface->counter--; - } - } - } - else if(v3 != -1) - /* this is some special case, 4th corner of this polygon was created - * triangle -> quat */ - vface->v3 = v3; - vface->vvert3 = BLI_dlist_find_link(&(vert_vlayer->dl), vface->v3); - if(vface->vvert3) { - vface->vvert3->counter++; - vface->counter--; - } - else { - vface->v3 = -1; - vface->counter--; - } - - vface->flag &= ~FACE_SENT; - vface->flag |= FACE_CHANGED; - - if(vface->counter<1) { - vface->flag &= ~FACE_CHANGED; - recalculate_verseface_normals(vnode); - ((VGeomData*)vnode->data)->post_polygon_set_corner(vface); - } - else { - /* when all needed VerseVertexes weren't received, then VerseFace is added to - * the list of orphans waiting on needed vertexes */ - BLI_dlist_rem_item(&(vlayer->dl), vface->id); - BLI_addtail(&(vlayer->orphans), (void*)vface); - } - } -} - -/* - * callback function: float value was set up for VerseVert with vertex_id - */ -static void cb_g_vertex_set_real32( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 vertex_id, - real32 value) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct real32_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), vertex_id); - - if(item) { - item->value = value; - } - else { - item = create_real32_item(vlayer, vertex_id, value); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: int value was set up for VerseVert with vertex_id - */ -static void cb_g_vertex_set_uint32( - void *user_def, - VNodeID node_id, - VLayerID layer_id, - uint32 vertex_id, - uint32 value) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - struct uint32_item *item; - - if(!session) return; - - /* find needed node (we can be sure, that it is geometry node) */ - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - /* find layer containing uint_8 data */ - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - - /* try to find item*/ - item = BLI_dlist_find_link(&(vlayer->dl), vertex_id); - - if(item) { - item->value = value; - } - else { - item = create_uint32_item(vlayer, vertex_id, value); - BLI_dlist_add_item_index(&(vlayer->dl), item, item->id); - } -} - -/* - * callback function: polygon was deleted - */ -static void cb_g_vertex_delete_real32( - void *user_data, - VNodeID node_id, - uint32 vertex_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - VNode *vnode=NULL; - VLayer *vert_vlayer=NULL; - VerseVert *vvert=NULL; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - - vvert = BLI_dlist_find_link(&(vert_vlayer->dl), (unsigned int)vertex_id); - - if(!vvert) return; - - if(vvert->counter < 1) { - ((VGeomData*)vnode->data)->post_vertex_delete(vvert); - BLI_dlist_free_item(&(vert_vlayer->dl), (unsigned int)vertex_id); - } - else { - /* some VerseFace(s) still need VerseVert, remove verse vert from - * list verse vertexes and put it to list of orphans */ - vvert->flag |= VERT_DELETED; - BLI_dlist_rem_item(&(vert_vlayer->dl), (unsigned int)vertex_id); - BLI_addtail(&(vert_vlayer->orphans), vvert); - } -} - -/* - * callback function: position of one vertex was changed or new vertex was created - */ -static void cb_g_vertex_set_xyz_real32( - void *user_data, - VNodeID node_id, - VLayerID layer_id, - uint32 vertex_id, - real32 x, - real32 y, - real32 z) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode = NULL; - struct VLayer *vlayer = NULL; - struct VerseVert *vvert = NULL; - real32 tmp; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode)return; - - vlayer = (VLayer*)BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), (unsigned int)layer_id); - if(!vlayer) return; - - /* switch axis orientation */ - tmp = y; - y = -z; - z = tmp; - - if(vlayer->id == 0) { - /* try to pick up verse vert from DynamicList */ - vvert = (VerseVert*)BLI_dlist_find_link(&(vlayer->dl), (unsigned int)vertex_id); - - if(vvert) { - if(vvert->flag & VERT_OBSOLETE) return; - - if (vvert->flag & VERT_LOCKED) { - /* this application changed position of this vertex */ - if((vvert->co[0]==x) && (vvert->co[1]==y) && (vvert->co[2]==z)) { - /* unlock vertex position */ - vvert->flag &= ~VERT_LOCKED; - /* call post_vertex_set_xyz only, when position of vertex is - * obsolete ... the new vertex position will be sent to - * verse server */ - if (vvert->flag & VERT_POS_OBSOLETE) { - ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert); - } - } - } - else { - /* somebody else changed position of this vertex*/ - if((vvert->co[0]!=x) || (vvert->co[1]!=y) || (vvert->co[2]!=z)) { - vvert->co[0] = x; - vvert->co[1] = y; - vvert->co[2] = z; - recalculate_verseface_normals(vnode); - ((VGeomData*)vnode->data)->post_vertex_set_xyz(vvert); - } - } - } - else { - /* create new verse vert */ - - /* test if we are authors of this vertex :-) */ - vvert = find_verse_vert_in_queue(vlayer, node_id, vertex_id, x, y, z); - - if(vvert) { - /* remove vert from queue */ - BLI_remlink(&(vlayer->queue), (void*)vvert); - /* add vvert to the dynamic list */ - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id); - /* set VerseVert flags */ - vvert->flag |= VERT_RECEIVED; - if(!(vvert->flag & VERT_POS_OBSOLETE)) - vvert->flag &= ~VERT_LOCKED; - /* find VerseFaces orphans */ - find_vlayer_orphans(vnode, vvert); - /* find unsent VerseFaces */ - find_unsent_faces(vnode, vvert); - } - else { - /* create new VerseVert */ - vvert = create_verse_vertex(vlayer, vertex_id, x, y, z); - /* add VerseVert to list of VerseVerts */ - BLI_dlist_add_item_index(&(vlayer->dl), (void*)vvert, (unsigned int)vertex_id); - /* set VerseVert flags */ - vvert->flag |= VERT_RECEIVED; - /* find VerseFaces orphans */ - find_vlayer_orphans(vnode, vvert); - } - - ((VGeomData*)vnode->data)->post_vertex_create(vvert); - } - } -} - -/* - * callback function for destroyng of verse layer - */ -static void cb_g_layer_destroy( - void *user_data, - VNodeID node_id, - VLayerID layer_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLayer *vlayer; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), node_id); - if(!vnode) return; - - vlayer = (VLayer*) BLI_dlist_find_link(&(((VGeomData*)vnode->data)->layers), layer_id); - - if(vlayer){ - /* free VerseLayer data */ - free_verse_layer_data(vnode, vlayer); - /* remove VerseLayer from list of verse layers */ - BLI_dlist_rem_item(&(((VGeomData*)vnode->data)->layers), layer_id); - /* do client dependent actions */ - vlayer->post_layer_destroy(vlayer); - /* free vlayer itself */ - MEM_freeN(vlayer); - } - -} - -/* - * callback function: new layer was created - */ -static void cb_g_layer_create( - void *user_data, - VNodeID node_id, - VLayerID layer_id, - const char *name, - VNGLayerType type, - uint32 def_integer, - real64 def_real) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode=NULL; - struct VLayer *vlayer=NULL; - - if(!session) return; - - /* find node of this layer*/ - vnode = BLI_dlist_find_link(&(session->nodes), node_id); - if(!vnode) return; - - /* when we created this layer, then subscribe to this layer */ - if(vnode->owner_id == VN_OWNER_MINE || session->flag & VERSE_AUTOSUBSCRIBE) - verse_send_g_layer_subscribe(node_id, layer_id, 0); - - /* try to find */ - if(vnode->owner_id == VN_OWNER_MINE) - vlayer = find_vlayer_in_sending_queue(vnode, layer_id); - - if(vlayer) { - /* remove vlayer form sending queue add verse layer to list of verse layers */ - BLI_remlink(&((VGeomData*)vnode->data)->queue, vlayer); - BLI_dlist_add_item_index(&((VGeomData*)vnode->data)->layers, (void*)vlayer, (unsigned int)vlayer->id); - /* send all not sent vertexes to verse server - * other items waiting in sending queue will be automaticaly sent to verse server, - * when verse vertexes will be received from verse server */ - if((vlayer->type == VN_G_LAYER_VERTEX_XYZ) && (layer_id==0)) { - struct VerseVert *vvert = (VerseVert*)vlayer->queue.first; - while(vvert) { - send_verse_vertex(vvert); - vvert = vvert->next; - } - } - } - else { - /* create new VerseLayer */ - vlayer = create_verse_layer(vnode, layer_id, name, type, def_integer, def_real); - /* add layer to the list of VerseLayers */ - BLI_dlist_add_item_index(&(((VGeomData*)vnode->data)->layers), (void*)vlayer, (unsigned int)layer_id); - } - - vlayer->flag |= LAYER_RECEIVED; - - /* post callback function */ - vlayer->post_layer_create(vlayer); -} - -/* - * this function will send destroy commands for all VerseVertexes and - * VerseFaces to verse server, but it will not send destroy commands - * for VerseLayers or geometry node, it can be used in other functions - * (undo, destroy geom node, some edit mesh commands, ... ), parameter of - * this function has to be geometry verse node - */ -void destroy_geometry(VNode *vnode) -{ - struct VLayer *vert_vlayer, *face_vlayer; - struct VerseFace *vface; - struct VerseVert *vvert; - - if(vnode->type != V_NT_GEOMETRY) return; - - face_vlayer = find_verse_layer_type((VGeomData*)vnode->data, POLYGON_LAYER); - vface = face_vlayer->dl.lb.first; - - while(vface) { - send_verse_face_delete(vface); - vface = vface->next; - } - - vert_vlayer = find_verse_layer_type((VGeomData*)vnode->data, VERTEX_LAYER); - vvert = vert_vlayer->dl.lb.first; - - while(vvert) { - send_verse_vertex_delete(vvert); - vvert = vvert->next; - } - - /* own destruction of local verse date will be executed, when client will - * receive apropriate callback commands from verse server */ -} - -/* - * free VGeomData - */ -void free_geom_data(VNode *vnode) -{ - struct VerseSession *session = vnode->session; - struct VLayer *vlayer; - - if(vnode->data){ - vlayer = (VLayer*)((VGeomData*)vnode->data)->layers.lb.first; - while(vlayer){ - /* unsubscribe from layer */ - if(session->flag & VERSE_CONNECTED) - verse_send_g_layer_unsubscribe(vnode->id, vlayer->id); - /* free VerseLayer data */ - free_verse_layer_data(vnode, vlayer); - /* next layer */ - vlayer = vlayer->next; - } - /* free constraint between vnode and mesh */ - ((VGeomData*)vnode->data)->post_geometry_free_constraint(vnode); - /* free all VerseLayers */ - BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers)); - /* free fake verse edges */ - BLI_freelistN(&((VGeomData*)vnode->data)->edges); - /* free edge hash */ - MEM_freeN(((VGeomData*)vnode->data)->hash); - } -} - -void set_geometry_callbacks(void) -{ - /* new layer created */ - verse_callback_set(verse_send_g_layer_create, cb_g_layer_create, NULL); - /* layer was destroyed */ - verse_callback_set(verse_send_g_layer_destroy, cb_g_layer_destroy, NULL); - - /* position of vertex was changed */ - verse_callback_set(verse_send_g_vertex_set_xyz_real32, cb_g_vertex_set_xyz_real32, NULL); - /* vertex was deleted */ - verse_callback_set(verse_send_g_vertex_delete_real32, cb_g_vertex_delete_real32, NULL); - - /* callback functions for values being associated with vertexes */ - verse_callback_set(verse_send_g_vertex_set_uint32, cb_g_vertex_set_uint32, NULL); - verse_callback_set(verse_send_g_vertex_set_real32, cb_g_vertex_set_real32, NULL); - - /* new polygon was created / vertex(es) of polygon was set */ - verse_callback_set(verse_send_g_polygon_set_corner_uint32, cb_g_polygon_set_corner_uint32, NULL); - /* polygon was deleted */ - verse_callback_set(verse_send_g_polygon_delete, cb_g_polygon_delete, NULL); - - /* callback functions for values being associated with polygon corners */ - verse_callback_set(verse_send_g_polygon_set_corner_real32, cb_g_polygon_set_corner_real32, NULL); - /* callback functions for values being associated with faces */ - verse_callback_set(verse_send_g_polygon_set_face_uint8, cb_g_polygon_set_face_uint8, NULL); - verse_callback_set(verse_send_g_polygon_set_face_uint32, cb_g_polygon_set_face_uint32, NULL); - verse_callback_set(verse_send_g_polygon_set_face_real32, cb_g_polygon_set_face_real32, NULL); - - /* crease of vertex was set */ - verse_callback_set(verse_send_g_crease_set_vertex, cb_g_crease_set_vertex, NULL); - /* crease of edge was set */ - verse_callback_set(verse_send_g_crease_set_edge, cb_g_crease_set_edge, NULL); -} - -#endif diff --git a/source/blender/blenkernel/intern/verse_method.c b/source/blender/blenkernel/intern/verse_method.c deleted file mode 100644 index 30886782019..00000000000 --- a/source/blender/blenkernel/intern/verse_method.c +++ /dev/null @@ -1,520 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Nathan Letwory. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" -#include "DNA_userdef_types.h" -#include "DNA_text_types.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "BIF_verse.h" - -#include "BKE_bad_level_calls.h" -#include "BKE_library.h" -#include "BKE_text.h" -#include "BKE_verse.h" -#include "BKE_global.h" -#include "BKE_main.h" - -#include "verse.h" - -/* helper struct for creating method descriptions */ -typedef struct VMethodInfo { - const char *name; - uint8 param_count; - const VNOParamType param_type[4]; - const char *param_name[4]; - uint16 id; -} VMethodInfo; - -#ifdef VERSECHAT -/* array with methods for verse chat */ -static VMethodInfo vmethod_info[] = { - { "join", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}}, - { "leave", 1, { VN_O_METHOD_PTYPE_STRING }, { "channel"}}, - { "hear", 3, { VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING, VN_O_METHOD_PTYPE_STRING }, { "channel", "from", "msg"}} -}; -#endif - -/* lookup a method group based on its name */ -struct VMethodGroup *lookup_vmethodgroup_name(ListBase *lb, const char *name) { - struct VMethodGroup *vmg; - - for(vmg= lb->first; vmg; vmg= vmg->next) - if(strcmp(vmg->name,name)==0) break; - - return vmg; -} - -/* lookup a method group based on its group_id */ -struct VMethodGroup *lookup_vmethodgroup(ListBase *lb, uint16 group_id) { - struct VMethodGroup *vmg; - - for(vmg= lb->first; vmg; vmg= vmg->next) - if(vmg->group_id==group_id) break; - - return vmg; -} - -/* lookup a method based on its name */ -struct VMethod *lookup_vmethod_name(ListBase *lb, const char *name) { - struct VMethod *vm; - for(vm= lb->first; vm; vm= vm->next) - if(strcmp(vm->name,name)==0) break; - - return vm; -} - -/* lookup a method based on its method_id */ -struct VMethod *lookup_vmethod(ListBase *lb, uint8 method_id) { - struct VMethod *vm; - for(vm= lb->first; vm; vm= vm->next) - if(vm->id==method_id) break; - - return vm; -} - -#ifdef VERSECHAT -/* - * send say command - */ -void send_say(const char *chan, const char *utter) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - struct VMethod *vm; - VNOPackedParams *utterpack; - VNOParam args[2]; - - vnode= (VNode *)(session->nodes.lb.first); - - for( ; vnode; vnode= vnode->next) { - if(strcmp(vnode->name, "tawksrv")==0) { - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); - if(!vmg) break; - vm= lookup_vmethod_name(&(vmg->methods), "say"); - if(!vm) break; - args[0].vstring= (char *)chan; - args[1].vstring= (char *)utter; - if((utterpack= verse_method_call_pack(vm->param_count, vm->param_type, args))!=NULL) { - verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, utterpack); - } - break; - } - - } -} - -/* - * send logout command - */ -void send_logout(VNode *vnode) -{ - struct VMethodGroup *vmg; - struct VMethod *vm; - VNOPackedParams *pack; - - vnode->chat_flag = CHAT_LOGGED; - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); - if(!vmg) return; - vm= lookup_vmethod_name(&(vmg->methods), "logout"); - if(!vm) return; - - if((pack= verse_method_call_pack(vm->param_count, vm->param_type, NULL))!=NULL) { - verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, pack); - } - vnode->chat_flag = CHAT_NOTLOGGED; -} - -/* - * send join command - */ -void send_join(VNode *vnode, const char *chan) -{ - struct VMethodGroup *vmg; - struct VMethod *vm; - VNOPackedParams *join; - VNOParam channel[1]; - - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); - if(!vmg) return; - vm= lookup_vmethod_name(&(vmg->methods), "join"); - if(!vm) return; - - channel[0].vstring= (char *)chan; - if((join= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) { - verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, join); - } -} - -/* - * send leave command - */ -void send_leave(VNode *vnode, const char *chan) -{ - struct VMethodGroup *vmg; - struct VMethod *vm; - VNOPackedParams *leave; - VNOParam channel[1]; - - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); - if(!vmg) return; - vm= lookup_vmethod_name(&(vmg->methods), "leave"); - if(!vm) return; - - channel[0].vstring= (char *)chan; - if((leave= verse_method_call_pack(vm->param_count, vm->param_type, channel))!=NULL) { - verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, leave); - } -} - -/* - * send login command - */ -void send_login(VNode *vnode) -{ - struct VMethodGroup *vmg; - struct VMethod *vm; - VNOPackedParams *login; - VNOParam param[1]; - - vnode->chat_flag = CHAT_LOGGED; - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk"); - if(!vmg) return; - vm= lookup_vmethod_name(&(vmg->methods), "login"); - if(!vm) return; - - param[0].vstring= U.verseuser; - - if((login= verse_method_call_pack(vm->param_count, vm->param_type, param))!=NULL) { - verse_send_o_method_call(vnode->id, vmg->group_id, vm->id, vnode->session->avatar, login); - } - vnode->chat_flag = CHAT_LOGGED; - - vnode= lookup_vnode(vnode->session, vnode->session->avatar); - vmg= lookup_vmethodgroup_name(&(vnode->methodgroups), "tawk-client"); - if(!vmg) - verse_send_o_method_group_create(vnode->session->avatar, ~0, "tawk-client"); -} -#endif - -/* - * Free a VMethod - */ -void free_verse_method(VMethod *vm) { - if(!vm) return; - - MEM_freeN(vm->param_type); -} - -/* - * Free methods for VMethodGroup - */ -void free_verse_methodgroup(VMethodGroup *vmg) -{ - struct VMethod *vm, *tmpvm; - - if(!vmg) return; - - vm= vmg->methods.first; - while(vm) { - tmpvm=vm->next; - free_verse_method(vm); - vm= tmpvm; - } - BLI_freelistN(&(vmg->methods)); -} - -/* callback for method group creation */ -static void cb_o_method_group_create( - void *user_data, - VNodeID node_id, - uint16 group_id, - const char *name) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - vmg = lookup_vmethodgroup(&(vnode->methodgroups), group_id); - - /* create method group holder in node node_id */ - if(!vmg) { - vmg= MEM_mallocN(sizeof(VMethodGroup), "VMethodGroup"); - vmg->group_id = group_id; - vmg->methods.first = vmg->methods.last = NULL; - BLI_addtail(&(vnode->methodgroups), vmg); - printf("new method group with name %s (group_id %d) for node %u created\n", name, group_id, node_id); - } - - /* this ensures name of an existing group gets updated, in case it is changed */ - BLI_strncpy(vmg->name, (char *)name, 16); - - /* subscribe to method group */ - verse_send_o_method_group_subscribe(node_id, group_id); - -#ifdef VERSECHAT - /* if this is our own method group, register our methods */ - if(node_id==session->avatar) { - verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[0].name, - vmethod_info[0].param_count, - (VNOParamType *)vmethod_info[0].param_type, - (const char **)vmethod_info[0].param_name); - b_verse_update(); - verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[1].name, - vmethod_info[1].param_count, - (VNOParamType *)vmethod_info[1].param_type, - (const char **)vmethod_info[1].param_name); - b_verse_update(); - verse_send_o_method_create(node_id, group_id, (uint8)~0u, vmethod_info[2].name, - vmethod_info[2].param_count, - (VNOParamType *)vmethod_info[2].param_type, - (const char **)vmethod_info[2].param_name); - b_verse_update(); - } -#endif -} - -/* callback for method group destruction */ -static void cb_o_method_group_destroy( - void *user_data, - VNodeID node_id, - uint16 group_id, - const char *name) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - struct VMethod *vm; - - printf("method group %d destroyed\n", group_id); - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next) - if(vmg->group_id==group_id) break; - - if(!vmg) return; /* method group doesn't exist? */ - - vmg->group_id = 0; - vmg->name[0] = '\0'; - vm= vmg->methods.first; - while(vm) { - /* free vm */ - - } - - /* TODO: unsubscribe from method group */ - BLI_remlink(&(vnode->methodgroups),vmg); - MEM_freeN(vmg); -} - -/* callback for method creation */ -static void cb_o_method_create( - void *user_data, - VNodeID node_id, - uint16 group_id, - uint16 method_id, - const char *name, - uint8 param_count, - const VNOParamType *param_type, - const char *param_name[]) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - struct VMethod *vm; - unsigned int size; - unsigned int i; - char *put; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - vmg= lookup_vmethodgroup((&vnode->methodgroups), group_id); - - if(!vmg) return; - - vm= lookup_vmethod((&vmg->methods), method_id); - - if(!vm) { - vm= MEM_mallocN(sizeof(VMethod), "VMethod"); - vm->id= method_id; - vm->param_count= param_count; - size= param_count* (sizeof(*vm->param_type) + sizeof(*vm->param_name)); - for(i= 0; i <param_count; i++) { - size+=strlen(param_name[i])+1; - } - vm->param_type= MEM_mallocN(size, "param_type and param_name"); - memcpy(vm->param_type, param_type, sizeof(VNOParamType)*param_count); - vm->param_name= (char **)(vm->param_type + param_count); - put= (char *)(vm->param_name + param_count); - for(i= 0; i < param_count; i++) { - vm->param_name[i]= put; - strcpy(put, param_name[i]); - put += strlen(param_name[i]) + 1; - } - - BLI_addtail(&(vmg->methods), vm); -#ifdef VERSECHAT - if(strcmp(vmethod_info[0].name, name)==0) { - vmethod_info[0].id = method_id; - } -#endif - printf("method %s in group %d of node %u created\n", name, group_id, node_id); - } - - BLI_strncpy(vm->name, (char *)name, 500); -} - -/* callback for method destruction */ -static void cb_o_method_destroy( - void *user_data, - VNodeID node_id, - uint16 group_id, - uint16 method_id, - const char *name, - uint8 param_count, - const VNOParamType *param_type, - const char *param_name[]) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - struct VMethod *vm; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - for(vmg= vnode->methodgroups.first; vmg; vmg= vmg->next) - if(vmg->group_id==group_id) break; - - if(!vmg) return; /* method group doesn't exist? */ - - for(vm= vmg->methods.first; vm; vm= vm->next) - if(vm->id==method_id) break; - - if(!vm) return; - - BLI_remlink(&(vmg->methods), vm); - MEM_freeN(vm->param_type); - MEM_freeN(vm); -} - -/* callback for method calls */ -static void cb_o_method_call(void *user_data, VNodeID node_id, uint8 group_id, uint8 method_id, VNodeID sender, VNOPackedParams *params) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VMethodGroup *vmg; - struct VMethod *vm; - Text *text; - int method_idx= -1; - - VNOParam arg[3]; - - if(!session) return; - - if(session->avatar!=node_id) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - vmg= lookup_vmethodgroup(&(vnode->methodgroups), group_id); - if(!vmg) return; - - vm= lookup_vmethod(&(vmg->methods), method_id); - if(!vm) return; -#ifdef VERSECHAT - if(strcmp(vm->name, "join")==0) method_idx=0; - if(strcmp(vm->name, "leave")==0) method_idx=1; - if(strcmp(vm->name, "hear")==0) method_idx=2; - if(method_idx>-1) - verse_method_call_unpack(params, vmethod_info[method_idx].param_count, vmethod_info[method_idx].param_type, arg); - - switch(method_idx) { - case 0: - printf("Joining channel %s\n",arg[0].vstring); - text=add_empty_text(); - text->flags |= TXT_ISCHAT; - rename_id(&(text->id), arg[0].vstring); - break; - case 1: - printf("Leaving channel %s\n",arg[0].vstring); - break; - case 2: - { - ListBase lb = G.main->text; - ID *id= (ID *)lb.first; - char showstr[1024]; - showstr[0]='\0'; - text = NULL; - sprintf(showstr, "%s: %s\n", arg[1].vstring, arg[2].vstring); - for(; id; id= id->next) { - if(strcmp(id->name+2, arg[0].vstring)==0 && strcmp(arg[0].vstring, "#server")!=0) { - text = (Text *)id; - break; - } - } - if(text) { - txt_insert_buf(text, showstr); - txt_move_eof(text, 0); - allqueue(REDRAWCHAT, 0); - } else { - printf("%s> %s: %s\n",arg[0].vstring, arg[1].vstring, arg[2].vstring); - } - } - break; - } -#endif -} - -void set_method_callbacks(void) -{ - /* create and destroy method groups */ - verse_callback_set(verse_send_o_method_group_create, cb_o_method_group_create, NULL); - verse_callback_set(verse_send_o_method_group_destroy, cb_o_method_group_destroy, NULL); - - /* create and destroy methods */ - verse_callback_set(verse_send_o_method_create, cb_o_method_create, NULL); - verse_callback_set(verse_send_o_method_destroy, cb_o_method_destroy, NULL); - - /* call methods */ - verse_callback_set(verse_send_o_method_call, cb_o_method_call, NULL); -} - -#endif diff --git a/source/blender/blenkernel/intern/verse_node.c b/source/blender/blenkernel/intern/verse_node.c deleted file mode 100644 index 1fe86f24d6e..00000000000 --- a/source/blender/blenkernel/intern/verse_node.c +++ /dev/null @@ -1,747 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Jiri Hnidek. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" -#include "DNA_userdef_types.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" - -#include "BIF_verse.h" - -#include "BKE_verse.h" - -#include "verse.h" - -/* function prototypes of static functions */ - /* for tags */ -static void free_verse_tag_data(struct VTag *vtag); -static struct VTag *find_tag_in_queue(struct VTagGroup *vtaggroup, const char *name); -static struct VTag *create_verse_tag(struct VTagGroup *vtaggroup, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); - /* for verse tag groups */ -static void free_verse_taggroup_data(struct VTagGroup *taggroup); -static struct VTagGroup *find_taggroup_in_queue(struct VNode *vnode, const char *name); -static struct VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name); - /* for verse nodes */ -static void move_verse_node_to_dlist(struct VerseSession *session, VNodeID vnode_id); - /* function prototypes of node callback functions */ -static void cb_tag_destroy(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id); -static void cb_tag_create(void *user_data, VNodeID node_id, uint16 group_id, uint16 tag_id, const char *name, VNTagType type, const VNTag *tag); -static void cb_tag_group_destroy(void *user_data, VNodeID node_id, uint16 group_id); -static void cb_tag_group_create(void *user_data, VNodeID node_id, uint16 group_id, const char *name); -static void cb_node_name_set(void *user_data, VNodeID node_id, const char *name); -static void cb_node_destroy(void *user_data, VNodeID node_id); -static void cb_node_create(void *user_data, VNodeID node_id, uint8 type, VNodeID owner_id); - -/* - * send new tag to verse server - */ -void send_verse_tag(VTag *vtag) -{ - verse_send_tag_create(vtag->vtaggroup->vnode->id, - vtag->vtaggroup->id, - vtag->id, - vtag->name, - vtag->type, - vtag->tag); -} - -/* - * free tag data - */ -static void free_verse_tag_data(VTag *vtag) -{ - /* free name of verse tag */ - MEM_freeN(vtag->name); - /* free value of tag */ - MEM_freeN(vtag->tag); -} - -/* - * try to find tag in sending queue ... if tag will be found, then - * this function will removed tag from queue and will return pointer - * at this tag - */ -static VTag *find_tag_in_queue(VTagGroup *vtaggroup, const char *name) -{ - struct VTag *vtag; - - vtag = vtaggroup->queue.first; - - while(vtag) { - if(strcmp(vtag->name, name)==0) { - BLI_remlink(&(vtaggroup->queue), vtag); - break; - } - vtag = vtag->next; - } - - return vtag; -} - -/* - * create new verse tag - */ -static VTag *create_verse_tag( - VTagGroup *vtaggroup, - uint16 tag_id, - const char *name, - VNTagType type, - const VNTag *tag) -{ - struct VTag *vtag; - - vtag = (VTag*)MEM_mallocN(sizeof(VTag), "VTag"); - - vtag->vtaggroup = vtaggroup; - vtag->id = tag_id; - vtag->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTag name"); - strcpy(vtag->name, name); - vtag->type = type; - - vtag->tag = (VNTag*)MEM_mallocN(sizeof(VNTag), "VNTag"); - *vtag->tag = *tag; - - vtag->value = NULL; - - return vtag; -} - -/* - * send taggroup to verse server - */ -void send_verse_taggroup(VTagGroup *vtaggroup) -{ - verse_send_tag_group_create( - vtaggroup->vnode->id, - vtaggroup->id, - vtaggroup->name); -} - -/* - * free taggroup data - */ -static void free_verse_taggroup_data(VTagGroup *taggroup) -{ - struct VerseSession *session = taggroup->vnode->session; - struct VTag *vtag; - - vtag = taggroup->tags.lb.first; - - while(vtag) { - free_verse_tag_data(vtag); - vtag = vtag->next; - } - - /* unsubscribe from taggroup */ - if(session->flag & VERSE_CONNECTED) - verse_send_tag_group_unsubscribe(taggroup->vnode->id, taggroup->id); - - BLI_dlist_destroy(&(taggroup->tags)); - MEM_freeN(taggroup->name); -} - -/* - * move taggroup from queue to dynamic list with access array, - * set up taggroup id and return pointer at this taggroup - */ -static VTagGroup *find_taggroup_in_queue(VNode *vnode, const char *name) -{ - struct VTagGroup *vtaggroup; - - vtaggroup = vnode->queue.first; - - while(vtaggroup) { - if(strcmp(vtaggroup->name, name)==0) { - BLI_remlink(&(vnode->queue), vtaggroup); - break; - } - vtaggroup = vtaggroup->next; - } - - return vtaggroup; -} - -/* - * create new verse group of tags - */ -static VTagGroup *create_verse_taggroup(VNode *vnode, uint16 group_id, const char *name) -{ - struct VTagGroup *taggroup; - - taggroup = (VTagGroup*)MEM_mallocN(sizeof(VTagGroup), "VTagGroup"); - - taggroup->vnode = vnode; - taggroup->id = group_id; - taggroup->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VTagGroup name"); - strcpy(taggroup->name, name); - - BLI_dlist_init(&(taggroup->tags)); - taggroup->queue.first = taggroup->queue.last = NULL; - - taggroup->post_tag_change = post_tag_change; - taggroup->post_taggroup_create = post_taggroup_create; - - return taggroup; -} - -/* - * move first VerseNode waiting in sending queue to dynamic list of VerseNodes - * (it usually happens, when "our" VerseNode was received from verse server) - */ -static void move_verse_node_to_dlist(VerseSession *session, VNodeID vnode_id) -{ - VNode *vnode; - - vnode = session->queue.first; - - if(vnode) { - BLI_remlink(&(session->queue), vnode); - BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, vnode_id); - } -} - -/* - * send VerseNode to verse server - */ -void send_verse_node(VNode *vnode) -{ - verse_send_node_create( - vnode->id, - vnode->type, - vnode->session->avatar); -} - -/* - * free Verse Node data - */ -void free_verse_node_data(VNode *vnode) -{ - struct VerseSession *session = vnode->session; - struct VTagGroup *vtaggroup; - - /* free node data (object, geometry, etc.) */ - switch(vnode->type){ - case V_NT_OBJECT: - free_object_data(vnode); - break; - case V_NT_GEOMETRY: - free_geom_data(vnode); - break; - case V_NT_BITMAP: - free_bitmap_node_data(vnode); - break; - default: - break; - } - - /* free all tag groups in dynamic list with access array */ - vtaggroup = vnode->taggroups.lb.first; - while(vtaggroup) { - free_verse_taggroup_data(vtaggroup); - vtaggroup = vtaggroup->next; - } - BLI_dlist_destroy(&(vnode->taggroups)); - - /* free all tag groups still waiting in queue */ - vtaggroup = vnode->queue.first; - while(vtaggroup) { - free_verse_taggroup_data(vtaggroup); - vtaggroup = vtaggroup->next; - } - BLI_freelistN(&(vnode->queue)); - - /* unsubscribe from node */ - if(session->flag & VERSE_CONNECTED) - verse_send_node_unsubscribe(vnode->id); - - /* free node name */ - MEM_freeN(vnode->name); - vnode->name = NULL; - - /* free node data */ - MEM_freeN(vnode->data); - vnode->data = NULL; - -} - -/* - * free VerseNode - */ -void free_verse_node(VNode *vnode) -{ - free_verse_node_data(vnode); - - BLI_dlist_free_item(&(vnode->session->nodes), vnode->id); -} - -/* - * Find a Verse Node from session - */ -VNode* lookup_vnode(VerseSession *session, VNodeID node_id) -{ - struct VNode *vnode; - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - return vnode; -} - -/* - * create new Verse Node - */ -VNode* create_verse_node(VerseSession *session, VNodeID node_id, uint8 type, VNodeID owner_id) -{ - struct VNode *vnode; - - vnode = (VNode*)MEM_mallocN(sizeof(VNode), "VerseNode"); - - vnode->session = session; - vnode->id = node_id; - vnode->owner_id = owner_id; - vnode->name = NULL; - vnode->type = type; - - BLI_dlist_init(&(vnode->taggroups)); - vnode->queue.first = vnode->queue.last = NULL; - vnode->methodgroups.first = vnode->methodgroups.last = NULL; - - vnode->data = NULL; - - vnode->counter = 0; - - vnode->flag = 0; -#ifdef VERSECHAT - vnode->chat_flag = CHAT_NOTLOGGED; -#endif - - vnode->post_node_create = post_node_create; - vnode->post_node_destroy = post_node_destroy; - vnode->post_node_name_set = post_node_name_set; - - return vnode; -} - -/* - * callback function: tag was destroyed - */ -static void cb_tag_destroy( - void *user_data, - VNodeID node_id, - uint16 group_id, - uint16 tag_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VTagGroup *vtaggroup; - struct VTag *vtag; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - /* try to find tag group in list of tag groups */ - vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); - - if(!vtaggroup) return; - - /* try to find verse tag in dynamic list of tags in tag group */ - vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); - - if(vtag) { - free_verse_tag_data(vtag); - BLI_dlist_free_item(&(vtaggroup->tags), vtag->id); - } -} - -/* - * callback function: new tag was created - */ -static void cb_tag_create( - void *user_data, - VNodeID node_id, - uint16 group_id, - uint16 tag_id, - const char *name, - VNTagType type, - const VNTag *tag) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VTagGroup *vtaggroup; - struct VTag *vtag; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - /* try to find tag group in list of tag groups */ - vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); - - if(!vtaggroup) return; - - /* try to find verse tag in dynamic list of tags in tag group */ - vtag = (VTag*)BLI_dlist_find_link(&(vtaggroup->tags), tag_id); - - if(!vtag) { - /* we will try to find vtag in sending queue */ - vtag = find_tag_in_queue(vtaggroup, name); - - /* when we didn't create this tag, then we will have to create one */ - if(!vtag) vtag = create_verse_tag(vtaggroup, tag_id, name, type, tag); - else vtag->id = tag_id; - - /* add tag to the list of tags in tag group */ - BLI_dlist_add_item_index(&(vtaggroup->tags), vtag, tag_id); - - /* post change/create method */ - vtaggroup->post_tag_change(vtag); - } - else { - /* this tag exists, then we will propably change value of this tag */ - if((vtag->type != type) || (strcmp(vtag->name, name)!=0)) { - /* changes of type or name are not allowed and such - * stupid changes will be returned back */ - send_verse_tag(vtag); - } - else { - /* post change/create method */ - vtaggroup->post_tag_change(vtag); - } - } -} - -/* - * callback function: tag group was destroyed - */ -static void cb_tag_group_destroy( - void *user_data, - VNodeID node_id, - uint16 group_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VTagGroup *vtaggroup; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); - - if(vtaggroup) { - free_verse_taggroup_data(vtaggroup); - BLI_dlist_free_item(&(vnode->taggroups), vtaggroup->id); - } -} - -/* - * callback function: new tag group was created - */ -static void cb_tag_group_create( - void *user_data, - VNodeID node_id, - uint16 group_id, - const char *name) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VTagGroup *vtaggroup; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(!vnode) return; - - /* name of taggroup has to begin with string "blender:" */ - if(strncmp("blender:", name, 8)) return; - - /* try to find tag group in list of tag groups */ - vtaggroup = BLI_dlist_find_link(&(vnode->taggroups), group_id); - - if(!vtaggroup) { - /* subscribe to tag group (when new tag will be created, then blender will - * receive command about it) */ - verse_send_tag_group_subscribe(vnode->id, group_id); - verse_callback_update(0); - - /* try to find taggroup in waiting queue */ - vtaggroup = find_taggroup_in_queue(vnode, name); - - /* if no taggroup exist, then new has to be created */ - if(!vtaggroup) vtaggroup = create_verse_taggroup(vnode, group_id, name); - else vtaggroup->id = group_id; - - /* add tag group to dynamic list with access array */ - BLI_dlist_add_item_index(&(vnode->taggroups), (void*)vtaggroup, (unsigned int)group_id); - - /* post create method */ - vtaggroup->post_taggroup_create(vtaggroup); - } - else { - /* this taggroup exist and somebody try to change its name */ - if(strcmp(vtaggroup->name, name)!=0) { - /* blender doesn't allow such stupid and dangerous things */ - send_verse_taggroup(vtaggroup); - } - } -} - -/* - * callback function: change name of node - */ -static void cb_node_name_set( - void *user_data, - VNodeID node_id, - const char *name) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - - if(!session) return; - - vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - if(vnode && name) { - if(!vnode->name) { - vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); - } - else if(strlen(name) > strlen(vnode->name)) { - MEM_freeN(vnode->name); - vnode->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "VerseNode name"); - } - strcpy(vnode->name, name); - - vnode->post_node_name_set(vnode); - } -} - -/* - * callback function for deleting node - */ -static void cb_node_destroy( - void *user_data, - VNodeID node_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - if(vnode) { - /* remove VerseNode from dynamic list */ - BLI_dlist_rem_item(&(session->nodes), (unsigned int)node_id); - /* do post destroy operations */ - vnode->post_node_destroy(vnode); - /* free verse data */ - free_verse_node_data(vnode); - /* free VerseNode */ - MEM_freeN(vnode); - }; -} - - -/* - * callback function for new created node - */ -static void cb_node_create( - void *user_data, - VNodeID node_id, - uint8 type, - VNodeID owner_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode = NULL; - - if(!session) return; - - /* subscribe to node */ - if((type==V_NT_OBJECT) || (type==V_NT_GEOMETRY) || (type==V_NT_BITMAP)) - verse_send_node_subscribe(node_id); - else - return; - - switch(type){ - case V_NT_OBJECT : - if(owner_id==VN_OWNER_MINE) { - struct VLink *vlink; - /* collect VerseNode from VerseNode queue */ - move_verse_node_to_dlist(session, node_id); - /* send next VerseNode waiting in queue */ - if(session->queue.first) send_verse_node(session->queue.first); - /* get received VerseNode from list of VerseNodes */ - vnode = BLI_dlist_find_link(&(session->nodes), node_id); - /* set up ID */ - vnode->id = node_id; - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* find unsent link pointing at this VerseNode */ - vlink = find_unsent_child_vlink(session, vnode); - /* send VerseLink */ - if(vlink) send_verse_link(vlink); - /* send name of object node */ - verse_send_node_name_set(node_id, vnode->name); - /* subscribe to changes of object node transformations */ - verse_send_o_transform_subscribe(node_id, 0); - /* send object transformation matrix */ - send_verse_object_position(vnode); - send_verse_object_rotation(vnode); - send_verse_object_scale(vnode); - } - else { - /* create new VerseNode */ - vnode = create_verse_node(session, node_id, type, owner_id); - /* add VerseNode to list of nodes */ - BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* create object data */ - vnode->data = create_object_data(); - /* set up avatar's name */ - if(node_id == session->avatar) { - verse_send_node_name_set(node_id, U.verseuser); - } - else if(session->flag & VERSE_AUTOSUBSCRIBE) { - /* subscribe to changes of object node transformations */ - verse_send_o_transform_subscribe(node_id, 0); - } - } - break; - case V_NT_GEOMETRY : - if(owner_id==VN_OWNER_MINE){ - struct VLink *vlink; - struct VLayer *vlayer; - /* collect VerseNode from VerseNode queue */ - move_verse_node_to_dlist(session, node_id); - /* send next VerseNode waiting in queue */ - if(session->queue.first) send_verse_node(session->queue.first); - /* get received VerseNode from list of VerseNodes */ - vnode = BLI_dlist_find_link(&(session->nodes), node_id); - /* set up ID */ - vnode->id = node_id; - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* find unsent link pointing at this VerseNode */ - vlink = find_unsent_parent_vlink(session, vnode); - /* send VerseLink */ - if(vlink) send_verse_link(vlink); - /* send name of geometry node */ - verse_send_node_name_set(node_id, vnode->name); - /* send all not sent layer to verse server */ - vlayer = (VLayer*)((VGeomData*)vnode->data)->queue.first; - if(vlayer) { - while(vlayer) { - send_verse_layer(vlayer); - vlayer = vlayer->next; - } - } - else { - /* send two verse layers to verse server */ -/* verse_send_g_layer_create(node_id, 0, "vertex", VN_G_LAYER_VERTEX_XYZ, 0, 0); - verse_send_g_layer_create(node_id, 1, "polygon", VN_G_LAYER_POLYGON_CORNER_UINT32, 0, 0);*/ - } - } - else { - /* create new VerseNode*/ - vnode = create_verse_node(session, node_id, type, owner_id); - /* add VerseNode to dlist of nodes */ - BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* create geometry data */ - vnode->data = (void*)create_geometry_data(); - } - break; - case V_NT_BITMAP : - if(owner_id==VN_OWNER_MINE) { - /* collect VerseNode from VerseNode queue */ - move_verse_node_to_dlist(session, node_id); - /* send next VerseNode waiting in queue */ - if(session->queue.first) send_verse_node(session->queue.first); - /* get received VerseNode from list of VerseNodes */ - vnode = BLI_dlist_find_link(&(session->nodes), node_id); - /* set up ID */ - vnode->id = node_id; - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* send name of object node */ - verse_send_node_name_set(node_id, vnode->name); - /* send dimension of image to verse server */ - verse_send_b_dimensions_set(node_id, - ((VBitmapData*)vnode->data)->width, - ((VBitmapData*)vnode->data)->height, - ((VBitmapData*)vnode->data)->depth); - } - else { - /* create new VerseNode*/ - vnode = create_verse_node(session, node_id, type, owner_id); - /* add VerseNode to dlist of nodes */ - BLI_dlist_add_item_index(&(session->nodes), (void*)vnode, (unsigned int)node_id); - /* set up flags */ - vnode->flag |= NODE_RECEIVED; - /* create bitmap data */ - vnode->data = (void*)create_bitmap_data(); - } - break; - default: - vnode = NULL; - break; - } - - if(vnode) vnode->post_node_create(vnode); -} - -/* - * set up all callbacks for verse nodes - */ -void set_node_callbacks(void) -{ - /* new node created */ - verse_callback_set(verse_send_node_create, cb_node_create, NULL); - /* node was deleted */ - verse_callback_set(verse_send_node_destroy, cb_node_destroy, NULL); - /* name of node was set */ - verse_callback_set(verse_send_node_name_set, cb_node_name_set, NULL); - - /* new tag group was created */ - verse_callback_set(verse_send_tag_group_create, cb_tag_group_create, NULL); - /* tag group was destroy */ - verse_callback_set(verse_send_tag_group_destroy, cb_tag_group_destroy, NULL); - - /* new tag was created */ - verse_callback_set(verse_send_tag_create, cb_tag_create, NULL); - /* tag was destroy */ - verse_callback_set(verse_send_tag_destroy, cb_tag_destroy, NULL); -} - -#endif diff --git a/source/blender/blenkernel/intern/verse_object_node.c b/source/blender/blenkernel/intern/verse_object_node.c deleted file mode 100644 index 89f9f0edcbd..00000000000 --- a/source/blender/blenkernel/intern/verse_object_node.c +++ /dev/null @@ -1,617 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Jiri Hnidek. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_listBase.h" -#include "DNA_userdef_types.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "BIF_verse.h" - -#include "BKE_verse.h" -#include "BKE_utildefines.h" - -#include "verse.h" - -/* function prototypes of static functions */ - -/* callback functions */ -static void cb_o_transform_pos_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const real32 *pos, const real32 *speed, const real32 *accelerate, const real32 *drag_normal, real32 drag); -static void cb_o_transform_rot_real32(void *user_data, VNodeID node_id, uint32 time_s, uint32 time_f, const VNQuat32 *temp, const VNQuat32 *speed, const VNQuat32 *accelerate, const VNQuat32 *drag_normal, real32 drag); -static void cb_o_transform_scale_real32(void *user_data, VNodeID node_id, real32 scale_x, real32 scale_y, real32 scale_z); -static void cb_o_link_set(void *user_data, VNodeID node_id, uint16 link_id, VNodeID link, const char *label, uint32 target_id); -static void cb_o_link_destroy(void *user_data, VNodeID node_id,uint16 link_id); - -/* other functions */ -static void set_target_node_link_pointer(struct VNode *vnode, struct VLink *vlink); -static void free_verse_link_data(struct VLink *vlink); - -/* - * find noy sent VerseLink in queue - */ -VLink *find_unsent_child_vlink(VerseSession *session, VNode *vnode) -{ - struct VLink *vlink; - - if(vnode->type!=V_NT_OBJECT) return NULL; - - vlink = ((VObjectData*)vnode->data)->queue.first; - while(vlink) { - if(vlink->target->id != -1) { - printf("\t vlink found, vnode target id %d\n", vlink->target->id); - return vlink; - } - vlink = vlink->next; - } - return NULL; -} - -/* - * find unsent VerseLink "pointing at this VerseNode" - */ -VLink *find_unsent_parent_vlink(VerseSession *session, VNode *vnode) -{ - struct VNode *tmp; - struct VLink *vlink; - - tmp = session->nodes.lb.first; - - while(tmp) { - if(tmp->type==V_NT_OBJECT) { - vlink = ((VObjectData*)tmp->data)->queue.first; - while(vlink) { - if(vlink->target == vnode) - return vlink; - vlink = vlink->next; - } - } - tmp = tmp->next; - } - return NULL; -} - -/* - * send object position to verse server - */ -void send_verse_object_position(VNode *vnode) -{ - float tmp; - - ((VObjectData*)vnode->data)->flag &= ~POS_SEND_READY; - - /* we have to do rotation around x axis (+pi/2) to be - compatible with other verse applications */ - tmp = -((VObjectData*)vnode->data)->pos[1]; - ((VObjectData*)vnode->data)->pos[1] = ((VObjectData*)vnode->data)->pos[2]; - ((VObjectData*)vnode->data)->pos[2] = tmp; - - verse_send_o_transform_pos_real32( - vnode->id, /* node id */ - 0, /* time_s ... no interpolation */ - 0, /* time_f ... no interpolation */ - ((VObjectData*)vnode->data)->pos, - NULL, /* speed ... no interpolation */ - NULL, /* accelerate ... no interpolation */ - NULL, /* drag normal ... no interpolation */ - 0.0); /* drag ... no interpolation */ -} - -/* - * send object rotation to verse server - */ -void send_verse_object_rotation(VNode *vnode) -{ - VNQuat32 quat; - float q[4] = {cos(-M_PI/4), -sin(-M_PI/4), 0, 0}, v[4], tmp[4]; - - /* inverse transformation to transformation in function cb_o_transform_rot_real32 */ - QuatMul(v, ((VObjectData*)vnode->data)->quat, q); - q[1]= sin(-M_PI/4); - QuatMul(tmp, q, v); - - quat.x = tmp[1]; - quat.y = tmp[2]; - quat.z = tmp[3]; - quat.w = tmp[0]; - - ((VObjectData*)vnode->data)->flag &= ~ROT_SEND_READY; - - verse_send_o_transform_rot_real32( - vnode->id, /* node id */ - 0, /* time_s ... no interpolation */ - 0, /* time_f ... no interpolation */ - &quat, - NULL, /* speed ... no interpolation */ - NULL, /* accelerate ... no interpolation */ - NULL, /* drag normal ... no interpolation */ - 0.0); /* drag ... no interpolation */ -} - -/* - * send object rotation to verse server - */ -void send_verse_object_scale(VNode *vnode) -{ - float tmp; - - ((VObjectData*)vnode->data)->flag &= ~SCALE_SEND_READY; - - /* we have to do rotation around x axis (+pi/2) to be - compatible with other verse applications */ - tmp = ((VObjectData*)vnode->data)->scale[1]; - ((VObjectData*)vnode->data)->scale[1] = ((VObjectData*)vnode->data)->scale[2]; - ((VObjectData*)vnode->data)->scale[2] = tmp; - - verse_send_o_transform_scale_real32( - vnode->id, - ((VObjectData*)vnode->data)->scale[0], - ((VObjectData*)vnode->data)->scale[1], - ((VObjectData*)vnode->data)->scale[2]); -} - -/* - * send VerseLink to verse server - */ -void send_verse_link(VLink *vlink) -{ - verse_session_set(vlink->session->vsession); - - verse_send_o_link_set( - vlink->source->id, - vlink->id, - vlink->target->id, - vlink->label, - vlink->target_id); -} - -/* - * set up pointer at VerseLink of target node (geometry node, material node, etc.) - */ -static void set_target_node_link_pointer(VNode *vnode, VLink *vlink) -{ - switch (vnode->type) { - case V_NT_GEOMETRY: - ((VGeomData*)vnode->data)->vlink = vlink; - break; - default: - break; - } -} - -/* - * free VerseLink and it's label - */ -static void free_verse_link_data(VLink *vlink) -{ - MEM_freeN(vlink->label); -} - -/* - * create new VerseLink - */ -VLink *create_verse_link( - VerseSession *session, - VNode *source, - VNode *target, - uint16 link_id, - uint32 target_id, - const char *label) -{ - struct VLink *vlink; - - vlink = (VLink*)MEM_mallocN(sizeof(VLink), "VerseLink"); - vlink->session = session; - vlink->source = source; - vlink->target = target; - vlink->id = link_id; - vlink->target_id = target_id; - - set_target_node_link_pointer(target, vlink); - - vlink->label = (char*)MEM_mallocN(sizeof(char)*(strlen(label)+1), "VerseLink label"); - vlink->label[0] = '\0'; - strcat(vlink->label, label); - - vlink->flag = 0; - - vlink->post_link_set = post_link_set; - vlink->post_link_destroy = post_link_destroy; - - return vlink; -} - -/* - * free ObjectData (links, links in queue and lables of links) - */ -void free_object_data(VNode *vnode) -{ - struct VerseSession *session = vnode->session; - struct VObjectData *obj = (VObjectData*)vnode->data; - struct VLink *vlink; - struct VMethodGroup *vmg; - - if(!obj) return; - - /* free all labels of links in dlist */ - vlink = obj->links.lb.first; - while(vlink){ - free_verse_link_data(vlink); - vlink = vlink->next; - } - - /* free all labels of links waiting in queue */ - vlink = obj->queue.first; - while(vlink){ - free_verse_link_data(vlink); - vlink = vlink->next; - } - /* free dynamic list and sendig queue of links */ - BLI_dlist_destroy(&(obj->links)); - BLI_freelistN(&(obj->queue)); - - /* free method groups and their methods */ - for(vmg = vnode->methodgroups.first; vmg; vmg= vmg->next) { - free_verse_methodgroup(vmg); - } - BLI_freelistN(&(vnode->methodgroups)); - - /* free constraint between VerseNode and Object */ - obj->post_object_free_constraint(vnode); - - /* unsubscribe from receiving changes of transformation matrix */ - if(session->flag & VERSE_CONNECTED) - verse_send_o_transform_unsubscribe(vnode->id, 0); -} - -/* - * create new object data - */ -VObjectData *create_object_data(void) -{ - VObjectData *obj; - - obj = (VObjectData*)MEM_mallocN(sizeof(VObjectData), "VerseObjectData"); - obj->object = NULL; - BLI_dlist_init(&(obj->links)); - obj->queue.first = obj->queue.last = NULL; - obj->flag = 0; - - /* transformation matrix */ - obj->pos[0] = obj->pos[1] = obj->pos[2] = 0.0; - obj->quat[0] = obj->quat[1] = obj->quat[2] = 0.0; obj->quat[3] = 1; - obj->scale[0] = obj->scale[1] = obj->scale[2] = 1.0; - - /* transformation flags */ - obj->flag |= POS_SEND_READY; - obj->flag |= ROT_SEND_READY; - obj->flag |= SCALE_SEND_READY; - - /* set up pointers at post callback functions */ -/* obj->post_transform = post_transform;*/ - obj->post_transform_pos = post_transform_pos; - obj->post_transform_rot = post_transform_rot; - obj->post_transform_scale = post_transform_scale; - obj->post_object_free_constraint = post_object_free_constraint; - - return obj; -} - -/* - * callback function: - */ -static void cb_o_transform_pos_real32( - void *user_data, - VNodeID node_id, - uint32 time_s, - uint32 time_f, - const real32 *pos, - const real32 *speed, - const real32 *accelerate, - const real32 *drag_normal, - real32 drag) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - float vec[3], dt, tmp; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - ((VObjectData*)vnode->data)->flag |= POS_SEND_READY; - - /* verse server sends automaticaly some stupid default values ... - * we have to ignore these values, when we created this object node */ - if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & POS_RECEIVE_READY) ) { - ((VObjectData*)vnode->data)->flag |= POS_RECEIVE_READY; - return; - } - - dt = time_s + time_f/(0xffff); - - if(pos) { - vec[0] = pos[0]; - vec[1] = pos[1]; - vec[2] = pos[2]; - } - else { - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; - } - - if(speed) { - vec[0] += speed[0]*dt; - vec[1] += speed[1]*dt; - vec[2] += speed[2]*dt; - } - - if(accelerate) { - vec[0] += accelerate[0]*dt*dt/2; - vec[1] += accelerate[1]*dt*dt/2; - vec[2] += accelerate[2]*dt*dt/2; - } - - /* we have to do rotation around x axis (+pi/2) to be - compatible with other verse applications */ - tmp = vec[1]; - vec[1] = -vec[2]; - vec[2] = tmp; - - if( (((VObjectData*)vnode->data)->pos[0] != vec[0]) || - (((VObjectData*)vnode->data)->pos[1] != vec[1]) || - (((VObjectData*)vnode->data)->pos[2] != vec[2])) - { - ((VObjectData*)vnode->data)->pos[0] = vec[0]; - ((VObjectData*)vnode->data)->pos[1] = vec[1]; - ((VObjectData*)vnode->data)->pos[2] = vec[2]; - - ((VObjectData*)vnode->data)->post_transform_pos(vnode); - } -} - -/* - * callback function: - */ -static void cb_o_transform_rot_real32( - void *user_data, - VNodeID node_id, - uint32 time_s, - uint32 time_f, - const VNQuat32 *quat, - const VNQuat32 *speed, - const VNQuat32 *accelerate, - const VNQuat32 *drag_normal, - real32 drag) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - float temp[4]={0, 0, 0, 0}, v[4], dt; /* temporary quaternions */ - float q[4]={cos(M_PI/4), -sin(M_PI/4), 0, 0}; /* conjugate quaternion (represents rotation - around x-axis +90 degrees) */ - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY; - - /* verse server sends automaticaly some stupid default values ... - * we have to ignore these values, when we created this object node */ - if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & ROT_RECEIVE_READY) ) { - ((VObjectData*)vnode->data)->flag |= ROT_RECEIVE_READY; - return; - } - - dt = time_s + time_f/(0xffff); - - if(quat) { - temp[1] = quat->x; - temp[2] = quat->y; - temp[3] = quat->z; - temp[0] = quat->w; - } - - if(speed) { - temp[1] += speed->x*dt; - temp[2] += speed->y*dt; - temp[3] += speed->z*dt; - temp[0] += speed->w*dt; - } - - if(accelerate) { - temp[1] += accelerate->x*dt*dt/2; - temp[2] += accelerate->y*dt*dt/2; - temp[3] += accelerate->z*dt*dt/2; - temp[0] += accelerate->w*dt*dt/2; - } - - /* following matematical operation transform rotation: - * - * v' = quaternion * v * conjugate_quaternion - * - *, where v is original representation of rotation */ - - QuatMul(v, temp, q); - q[1]= sin(M_PI/4); /* normal quaternion */ - QuatMul(temp, q, v); - - if( (((VObjectData*)vnode->data)->quat[0] != temp[0]) || - (((VObjectData*)vnode->data)->quat[1] != temp[1]) || - (((VObjectData*)vnode->data)->quat[2] != temp[2]) || - (((VObjectData*)vnode->data)->quat[3] != temp[3])) - { - QUATCOPY(((VObjectData*)vnode->data)->quat, temp); - - ((VObjectData*)vnode->data)->post_transform_rot(vnode); - } -} - -/* - * callback function: - */ -static void cb_o_transform_scale_real32( - void *user_data, - VNodeID node_id, - real32 scale_x, - real32 scale_y, - real32 scale_z) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - real32 tmp; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY; - - /* verse server sends automaticaly some stupid default values ... - * we have to ignore these values, when we created this object node */ - if( (vnode->owner_id==VN_OWNER_MINE) && !(((VObjectData*)vnode->data)->flag & SCALE_RECEIVE_READY) ) { - ((VObjectData*)vnode->data)->flag |= SCALE_RECEIVE_READY; - return; - } - - /* flip axis (verse spec) */ - tmp = scale_y; - scale_y = scale_z; - scale_z = tmp; - - /* z and y axis are flipped here too */ - if( (((VObjectData*)vnode->data)->scale[0] != scale_x) || - (((VObjectData*)vnode->data)->scale[1] != scale_y) || - (((VObjectData*)vnode->data)->scale[2] != scale_z)) - { - ((VObjectData*)vnode->data)->scale[0] = scale_x; - ((VObjectData*)vnode->data)->scale[1] = scale_y; - ((VObjectData*)vnode->data)->scale[2] = scale_z; - - ((VObjectData*)vnode->data)->post_transform_scale(vnode); - } -} - -/* - * callback function: link between object node and some other node was created - */ -static void cb_o_link_set( - void *user_data, - VNodeID node_id, - uint16 link_id, - VNodeID link, - const char *label, - uint32 target_id) -{ - struct VLink *vlink; - struct VNode *source; - struct VNode *target; - - struct VerseSession *session = (VerseSession*)current_verse_session(); - - if(!session) return; - - source = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - target = BLI_dlist_find_link(&(session->nodes), (unsigned int)link); - - if(!(source && target)) return; - - vlink = ((VObjectData*)source->data)->queue.first; - - if(vlink && (vlink->source==source) && (vlink->target==target)) { - /* remove VerseLink from sending queue */ - BLI_remlink(&(((VObjectData*)source->data)->queue), vlink); - /* add VerseLink to dynamic list of VerseLinks */ - BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); - /* send next link from sending queue */ - if(((VObjectData*)source->data)->queue.first) - send_verse_link(((VObjectData*)source->data)->queue.first); - /* set up VerseLink variables */ - vlink->flag = 0; - vlink->id = link_id; - vlink->target_id = target_id; - } - else { - /* create new VerseLink */ - vlink = create_verse_link(session, source, target, link_id, target_id, label); - /* add VerseLink to dynamic list of VerseLinks */ - BLI_dlist_add_item_index(&(((VObjectData*)source->data)->links), vlink, (unsigned int)link_id); - } - - target->counter++; - - vlink->post_link_set(vlink); -} - -/* - * callback function: destroy link between two VerseNodes - */ -static void cb_o_link_destroy( - void *user_data, - VNodeID node_id, - uint16 link_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VNode *vnode; - struct VLink *vlink; - - if(!session) return; - - vnode = BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id); - - vlink = BLI_dlist_find_link(&(((VObjectData*)vnode->data)->links), link_id); - - if(vlink) { - vlink->target->counter--; - free_verse_link_data(vlink); - BLI_dlist_free_item(&(((VObjectData*)vnode->data)->links), link_id); - } - - vlink->post_link_destroy(vlink); -} - -void set_object_callbacks(void) -{ - /* position of object was changed */ - verse_callback_set(verse_send_o_transform_pos_real32, cb_o_transform_pos_real32, NULL); - /* rotation of object was changed */ - verse_callback_set(verse_send_o_transform_rot_real32, cb_o_transform_rot_real32, NULL); - /* size of object was changed */ - verse_callback_set(verse_send_o_transform_scale_real32, cb_o_transform_scale_real32, NULL); - /* new link between nodes was created */ - verse_callback_set(verse_send_o_link_set, cb_o_link_set, NULL); - /* link between nodes was destroyed */ - verse_callback_set(verse_send_o_link_destroy, cb_o_link_destroy, NULL); -} - -#endif diff --git a/source/blender/blenkernel/intern/verse_session.c b/source/blender/blenkernel/intern/verse_session.c deleted file mode 100644 index 28a9ef85536..00000000000 --- a/source/blender/blenkernel/intern/verse_session.c +++ /dev/null @@ -1,477 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Contributor(s): Jiri Hnidek. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef WITH_VERSE - -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" /* temp */ -#include "DNA_listBase.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" - -#include "BLI_dynamiclist.h" -#include "BLI_blenlib.h" - -#include "BIF_screen.h" -#include "BIF_verse.h" - -#include "BKE_global.h" -#include "BKE_verse.h" - -struct ListBase session_list={NULL, NULL}; -struct ListBase server_list={NULL, NULL}; - -static int cb_ping_registered = 0; - -/* list of static function prototypes */ -static void cb_connect_terminate(const char *address, const char *bye); -static void cb_connect_accept(void *user_data, uint32 avatar, void *address, void *connection, const uint8 *host_id); -static void set_all_callbacks(void); -static void free_verse_session_data(struct VerseSession *session); -static void add_verse_server(VMSServer *server); -static void check_connection_state(struct VerseServer *server); - -static void check_connection_state(struct VerseServer *server) -{ - struct VerseSession *session; - session = session_list.first; - while(session) { - if(strcmp(server->ip,session->address)==0) { - server->flag = session->flag; - return; - } - session = session->next; - } -} -/* - * add verse server to server_list. Prevents duplicate - * entries - */ -static void add_verse_server(VMSServer *server) -{ - struct VerseServer *iter, *niter; - VerseServer *newserver; - const char *name = verse_ms_field_value(server, "DE"); - iter = server_list.first; - - while(iter) { - niter = iter->next; - if(strcmp(iter->ip, server->ip)==0) { - return; - } - iter = niter; - } - - newserver = (VerseServer *)MEM_mallocN(sizeof(VerseServer), "VerseServer"); - newserver->ip = (char *)MEM_mallocN(sizeof(char)*(strlen(server->ip)+1), "VerseServer ip"); - strcpy(newserver->ip, server->ip); - - if(name) { - newserver->name = (char *)MEM_mallocN(sizeof(char)*(strlen(name)+strlen(newserver->ip)+4), "VerseServer name"); - strcpy(newserver->name, name); - strcat(newserver->name, " ("); - strcat(newserver->name, newserver->ip); - strcat(newserver->name, ")"); - } - - newserver->flag = 0; - check_connection_state(newserver); - - printf("Adding new verse server: %s at %s\n", newserver->name, newserver->ip); - - BLI_addtail(&server_list, newserver); - post_server_add(); -} - -/* - * callback function for ping - */ -static void cb_ping(void *user, const char *address, const char *message) -{ - VMSServer **servers = verse_ms_list_parse(message); - if(servers != NULL) - { - int i; - - for(i = 0; servers[i] != NULL; i++) - add_verse_server(servers[i]); - - free(servers); - } -} - -/* - * callback function for connection terminated - */ -static void cb_connect_terminate(const char *address, const char *bye) -{ - VerseSession *session = (VerseSession*)current_verse_session(); - - if(!session) return; - - /* remove session from list of session */ - BLI_remlink(&session_list, session); - /* do post connect operations */ - session->post_connect_terminated(session); - /* free session data */ - free_verse_session_data(session); - /* free session */ - MEM_freeN(session); -} - -/* - * callback function for accepted connection to verse server - */ -static void cb_connect_accept( - void *user_data, - uint32 avatar, - void *address, - void *connection, - const uint8 *host_id) -{ - struct VerseSession *session = (VerseSession*)current_verse_session(); - struct VerseServer *server = server_list.first; - uint32 i, mask=0; - - if(!session) return; - - session->flag |= VERSE_CONNECTED; - session->flag &= ~VERSE_CONNECTING; - - while(server) { - if(strcmp(session->address, server->ip)==0) { - server->flag |= VERSE_CONNECTED; - server->flag &= ~VERSE_CONNECTING; - server->session = session; - break; - } - server = server->next; - } - - printf("\tBlender is connected to verse server: %s\n", (char*)address); - printf("\tVerseSession->counter: %d\n", session->counter); - - session->avatar = avatar; - - session->post_connect_accept(session); - - for(i = 0; i < V_NT_NUM_TYPES; i++) - mask = mask | (1 << i); - verse_send_node_index_subscribe(mask); - verse_send_node_subscribe(session->avatar); /* subscribe to avatar node, as well */ - - /* create our own method group and method */ - /*verse_send_o_method_group_create(session->avatar, ~0, "tawk-client");*/ -} - -/* - * set up all callbacks for sessions - */ -void set_verse_session_callbacks(void) -{ - /* connection */ - verse_callback_set(verse_send_connect_accept, cb_connect_accept, NULL); - /* connection was terminated */ - verse_callback_set(verse_send_connect_terminate, cb_connect_terminate, NULL); - -} - -/* - * set all callbacks used in Blender - */ -static void set_all_callbacks(void) -{ - /* set up all callbacks for sessions */ - set_verse_session_callbacks(); - - /* set up callbacks for nodes */ - set_node_callbacks(); - - /* set up all callbacks for object nodes */ - set_object_callbacks(); - - /* set up all callbacks for geometry nodes */ - set_geometry_callbacks(); - - /* set up all callbacks for bitmap nodes */ - set_bitmap_callbacks(); - - /* set up all callbacks for method groups and methods */ - set_method_callbacks(); -} - -/* - * this function sends and receive all packets for all sessions - */ -void b_verse_update(void) -{ - VerseSession *session, *next_session; - - session = session_list.first; - while(session){ - next_session = session->next; - verse_session_set(session->vsession); - if((session->flag & VERSE_CONNECTED) || (session->flag & VERSE_CONNECTING)) { - verse_callback_update(10); - session->post_connect_update(session); - } - session = next_session; - } - if(cb_ping_registered>0) { - verse_callback_update(10); - } -} - -/* - * returns VerseSession coresponding to vsession pointer - */ -VerseSession *versesession_from_vsession(VSession *vsession) -{ - struct VerseSession *session; - - session = session_list.first; - - while(session) { - if(session->vsession==vsession) return session; - session = session->next; - } - - return session; -} - -/* - * returns pointer at current VerseSession - */ -VerseSession *current_verse_session(void) -{ - struct VerseSession *session; - VSession vsession = verse_session_get(); - - session = session_list.first; - - while(session){ - if(session->vsession == vsession) - return session; - session = session->next; - } - - printf("error: non-existing SESSION occured!\n"); - return NULL; -} - -/* - * free VerseSession - */ -static void free_verse_session_data(VerseSession *session) -{ - struct VNode *vnode; - - /* free data of all nodes */ - vnode = session->nodes.lb.first; - while(vnode){ - free_verse_node_data(vnode); - vnode = vnode->next; - } - - /* free data of nodes waiting in queue */ - vnode = session->queue.first; - while(vnode){ - free_verse_node_data(vnode); - vnode = vnode->next; - } - - /* free all VerseNodes */ - BLI_dlist_destroy(&(session->nodes)); - /* free all VerseNodes waiting in queque */ - BLI_freelistN(&(session->queue)); - - /* free name of verse host for this session */ - MEM_freeN(session->address); -} - -/* - * free VerseSession - */ -void free_verse_session(VerseSession *session) -{ - /* remove session from session list*/ - BLI_remlink(&session_list, session); - /* do post terminated operations */ - session->post_connect_terminated(session); - /* free session data (nodes, layers) */ - free_verse_session_data(session); - /* free session */ - MEM_freeN(session); -} - -/* - * create new verse session and return coresponding data structure - */ -VerseSession *create_verse_session( - const char *name, - const char *pass, - const char *address, - uint8 *expected_key) -{ - struct VerseSession *session; - VSession *vsession; - - vsession = verse_send_connect(name, pass, address, expected_key); - - if(!vsession) return NULL; - - session = (VerseSession*)MEM_mallocN(sizeof(VerseSession), "VerseSession"); - - session->flag = VERSE_CONNECTING; - - session->vsession = vsession; - session->avatar = -1; - - session->address = (char*)MEM_mallocN(sizeof(char)*(strlen(address)+1),"session adress name"); - strcpy(session->address, address); - - session->connection = NULL; - session->host_id = NULL; - session->counter = 0; - - /* initialize dynamic list of nodes and node queue */ - BLI_dlist_init(&(session->nodes)); - session->queue.first = session->queue.last = NULL; - - /* set up all client dependent functions */ - session->post_connect_accept = post_connect_accept; - session->post_connect_terminated = post_connect_terminated; - session->post_connect_update = post_connect_update; - - post_server_add(); - - return session; -} - -/* - * end verse session and free all session data - */ -void end_verse_session(VerseSession *session) -{ - /* send terminate command to verse server */ - verse_send_connect_terminate(session->address, "blender: bye bye"); - /* update callbacks */ - verse_callback_update(1000); - /* send destroy session command to verse server */ - verse_session_destroy(session->vsession); - /* set up flag of verse session */ - session->flag &= ~VERSE_CONNECTED; - /* do post connect operations */ - session->post_connect_terminated(session); - /* free structure of verse session */ - free_verse_session(session); -} - -void free_all_servers(void) -{ - VerseServer *server, *nextserver; - - server = server_list.first; - - while(server) { - nextserver = server->next; - BLI_remlink(&server_list, server); - MEM_freeN(server->name); - MEM_freeN(server->ip); - MEM_freeN(server); - server = nextserver; - } - - BLI_freelistN(&server_list); -} - -/* - * end connection to all verse hosts (servers) ... free all VerseSessions - * free all VerseServers - */ -void end_all_verse_sessions(void) -{ - VerseSession *session,*nextsession; - - session = session_list.first; - - while(session) { - nextsession= session->next; - end_verse_session(session); - /* end next session */ - session = nextsession; - } - - BLI_freelistN(&session_list); - - free_all_servers(); -} - -/* - * do a get from ms - */ -void b_verse_ms_get(void) -{ - if(cb_ping_registered==0) { - /* handle ping messages (for master server) */ - verse_callback_set(verse_send_ping, cb_ping, NULL); - add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1); - cb_ping_registered++; - } - free_all_servers(); - - verse_ms_get_send(U.versemaster, VERSE_MS_FIELD_DESCRIPTION, NULL); - verse_callback_update(10); -} - -/* - * connect to verse host, set up all callbacks, create session - */ -void b_verse_connect(char *address) -{ - VerseSession *session = NULL; - - /* if no session was created before, then set up all callbacks */ - if((session_list.first==NULL) && (session_list.last==NULL)) - set_all_callbacks(); - - /* create new session */ - if(address) - session = create_verse_session("Blender", "pass", address, NULL); - - if(session) { - /* add new session to the list of sessions */ - BLI_addtail(&session_list, session); - - /* add verse handler if this is first session */ - if(session_list.first == session_list.last) - add_screenhandler(G.curscreen, SCREEN_HANDLER_VERSE, 1); - - } -} - -#endif diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 6635ef29d51..7fe129ed6fc 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -45,10 +45,10 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" -#include "BKE_bad_level_calls.h" #include "BKE_utildefines.h" #include "BKE_library.h" +#include "BKE_animsys.h" #include "BKE_world.h" #include "BKE_global.h" #include "BKE_main.h" @@ -77,7 +77,8 @@ void free_world(World *wrld) } BKE_previewimg_free(&wrld->preview); - wrld->ipo= 0; + BKE_free_animdata((ID *)wrld); + BKE_icon_delete((struct ID*)wrld); wrld->id.icon_id = 0; } @@ -109,6 +110,10 @@ World *add_world(char *name) wrld->mode = WO_DBVT_CULLING; // DBVT culling by default wrld->occlusionRes = 128; wrld->preview = NULL; + wrld->ticrate = 60; + wrld->maxlogicstep = 5; + wrld->physubstep = 1; + wrld->maxphystep = 5; return wrld; } @@ -132,7 +137,10 @@ World *copy_world(World *wrld) #ifndef DISABLE_PYTHON BPY_copy_scriptlink(&wrld->scriptlink); #endif + +#if 0 // XXX old animation system id_us_plus((ID *)wrldn->ipo); +#endif // XXX old animation system return wrldn; } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 44004eeee80..f84bd690347 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -50,10 +50,6 @@ #include "quicktime_export.h" #endif -#if defined(_WIN32) && !defined(FREE_WINDOWS) -#include "BIF_writeavicodec.h" -#endif - #ifdef WITH_FFMPEG #include "BKE_writeffmpeg.h" #endif @@ -68,7 +64,7 @@ bMovieHandle *BKE_get_movie_handle(int imtype) mh.start_movie= start_avi; mh.append_movie= append_avi; mh.end_movie= end_avi; - mh.get_next_frame = 0; + mh.get_next_frame = NULL; /* do the platform specific handles */ #ifdef __sgi @@ -78,9 +74,9 @@ bMovieHandle *BKE_get_movie_handle(int imtype) #endif #if defined(_WIN32) && !defined(FREE_WINDOWS) if (imtype == R_AVICODEC) { - mh.start_movie= start_avi_codec; - mh.append_movie= append_avi_codec; - mh.end_movie= end_avi_codec; + //XXX mh.start_movie= start_avi_codec; + //XXX mh.append_movie= append_avi_codec; + //XXX mh.end_movie= end_avi_codec; } #endif #ifdef WITH_QUICKTIME @@ -175,7 +171,7 @@ void start_avi(RenderData *rd, int rectx, int recty) printf("Created avi: %s\n", name); } -void append_avi(int frame, int *pixels, int rectx, int recty) +void append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty) { unsigned int *rt1, *rt2, *rectot; int x, y; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index c3d8ed855a2..0277da5f908 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -57,24 +57,20 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BKE_bad_level_calls.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "BSE_seqaudio.h" - #include "DNA_scene_types.h" -#include "blendef.h" #ifdef HAVE_CONFIG_H #include <config.h> #endif extern void do_init_ffmpeg(); -void makeffmpegstring(char* string); +static void makeffmpegstring(RenderData* rd, char* string); static int ffmpeg_type = 0; static int ffmpeg_codec = CODEC_ID_MPEG4; @@ -100,8 +96,6 @@ static int audio_input_frame_size = 0; static uint8_t* audio_output_buffer = 0; static int audio_outbuf_size = 0; -static RenderData *ffmpeg_renderdata = 0; - #define FFMPEG_AUTOSPLIT_SIZE 2000000000 /* Delete a picture buffer */ @@ -133,9 +127,9 @@ static int write_audio_frame(void) c = get_codec_from_stream(audio_stream); - audiostream_fill(audio_input_buffer, - audio_input_frame_size - * sizeof(short) * c->channels); + //XXX audiostream_fill(audio_input_buffer, + // audio_input_frame_size + // * sizeof(short) * c->channels); av_init_packet(&pkt); @@ -154,7 +148,7 @@ static int write_audio_frame(void) pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_interleaved_write_frame(outfile, &pkt) != 0) { - error("Error writing audio packet"); + //XXX error("Error writing audio packet"); return -1; } return 0; @@ -240,14 +234,17 @@ static const char** get_file_extensions(int format) } /* Write a frame to the output file */ -static void write_video_frame(AVFrame* frame) +static void write_video_frame(RenderData *rd, AVFrame* frame) { int outsize = 0; int ret; AVCodecContext* c = get_codec_from_stream(video_stream); #ifdef FFMPEG_CODEC_TIME_BASE - frame->pts = G.scene->r.cfra - G.scene->r.sfra; + frame->pts = rd->cfra - rd->sfra; #endif + if (G.scene->r.mode & R_FIELDS) { + frame->top_field_first = ((G.scene->r.mode & R_ODDFIELD) != 0); + } outsize = avcodec_encode_video(c, video_buffer, video_buffersize, frame); @@ -276,7 +273,7 @@ static void write_video_frame(AVFrame* frame) } else ret = 0; if (ret != 0) { G.afbreek = 1; - error("Error writing frame"); + //XXX error("Error writing frame"); } } @@ -294,7 +291,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels) rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height); if (!rgb_frame) { G.afbreek=1; - error("Couldn't allocate temporary frame"); + //XXX error("Couldn't allocate temporary frame"); return NULL; } } else { @@ -306,7 +303,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels) /* Do RGBA-conversion and flipping in one step depending on CPU-Endianess */ - if (G.order == L_ENDIAN) { + if (ENDIAN_ORDER == L_ENDIAN) { int y; for (y = 0; y < height; y++) { uint8_t* target = rgb_frame->data[0] @@ -397,18 +394,18 @@ static void set_ffmpeg_property_option(AVCodecContext* c, IDProperty * prop) } } -static void set_ffmpeg_properties(AVCodecContext* c, const char * prop_name) +static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * prop_name) { IDProperty * prop; void * iter; IDProperty * curr; - if (!G.scene->r.ffcodecdata.properties) { + if (!rd->ffcodecdata.properties) { return; } prop = IDP_GetPropertyFromGroup( - G.scene->r.ffcodecdata.properties, (char*) prop_name); + rd->ffcodecdata.properties, (char*) prop_name); if (!prop) { return; } @@ -422,7 +419,7 @@ static void set_ffmpeg_properties(AVCodecContext* c, const char * prop_name) /* prepare a video stream for the output file */ -static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, +static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext* of, int rectx, int recty) { AVStream* st; @@ -445,39 +442,39 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, #ifdef FFMPEG_CODEC_TIME_BASE /* FIXME: Really bad hack (tm) for NTSC support */ - if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) { + if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) { c->time_base.den = 2997; c->time_base.num = 100; - } else if ((double) ((int) G.scene->r.frs_sec_base) == - G.scene->r.frs_sec_base) { - c->time_base.den = G.scene->r.frs_sec; - c->time_base.num = (int) G.scene->r.frs_sec_base; + } else if ((double) ((int) rd->frs_sec_base) == + rd->frs_sec_base) { + c->time_base.den = rd->frs_sec; + c->time_base.num = (int) rd->frs_sec_base; } else { - c->time_base.den = G.scene->r.frs_sec * 100000; - c->time_base.num = ((double) G.scene->r.frs_sec_base) * 100000; + c->time_base.den = rd->frs_sec * 100000; + c->time_base.num = ((double) rd->frs_sec_base) * 100000; } #else /* FIXME: Really bad hack (tm) for NTSC support */ - if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) { + if (ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) { c->frame_rate = 2997; c->frame_rate_base = 100; - } else if ((double) ((int) G.scene->r.frs_sec_base) == - G.scene->r.frs_sec_base) { - c->frame_rate = G.scene->r.frs_sec; - c->frame_rate_base = G.scene->r.frs_sec_base; + } else if ((double) ((int) rd->frs_sec_base) == + rd->frs_sec_base) { + c->frame_rate = rd->frs_sec; + c->frame_rate_base = rd->frs_sec_base; } else { - c->frame_rate = G.scene->r.frs_sec * 100000; - c->frame_rate_base = ((double) G.scene->r.frs_sec_base)*100000; + c->frame_rate = rd->frs_sec * 100000; + c->frame_rate_base = ((double) rd->frs_sec_base)*100000; } #endif c->gop_size = ffmpeg_gop_size; c->bit_rate = ffmpeg_video_bitrate*1000; - c->rc_max_rate = G.scene->r.ffcodecdata.rc_max_rate*1000; - c->rc_min_rate = G.scene->r.ffcodecdata.rc_min_rate*1000; - c->rc_buffer_size = G.scene->r.ffcodecdata.rc_buffer_size * 1024; + c->rc_max_rate = rd->ffcodecdata.rc_max_rate*1000; + c->rc_min_rate = rd->ffcodecdata.rc_min_rate*1000; + c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024; c->rc_initial_buffer_occupancy - = G.scene->r.ffcodecdata.rc_buffer_size*3/4; + = rd->ffcodecdata.rc_buffer_size*3/4; c->rc_buffer_aggressivity = 1.0; c->me_method = ME_EPZS; @@ -508,7 +505,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, } /* Determine whether we are encoding interlaced material or not */ - if (G.scene->r.mode & R_FIELDS) { + if (rd->mode & R_FIELDS) { fprintf(stderr, "Encoding interlaced video\n"); c->flags |= CODEC_FLAG_INTERLACED_DCT; c->flags |= CODEC_FLAG_INTERLACED_ME; @@ -517,12 +514,13 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, /* xasp & yasp got float lately... */ st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q( - ((double) G.scene->r.xasp / (double) G.scene->r.yasp), 255); + ((double) rd->xasp / (double) rd->yasp), 255); - set_ffmpeg_properties(c, "video"); + set_ffmpeg_properties(rd, c, "video"); if (avcodec_open(c, codec) < 0) { - error("Couldn't initialize codec"); + // + //XXX error("Couldn't initialize codec"); return NULL; } @@ -543,7 +541,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, /* Prepare an audio stream for the output file */ -static AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) +static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext* of) { AVStream* st; AVCodecContext* c; @@ -556,19 +554,19 @@ static AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) c->codec_id = codec_id; c->codec_type = CODEC_TYPE_AUDIO; - c->sample_rate = G.scene->audio.mixrate; + c->sample_rate = rd->audio.mixrate; c->bit_rate = ffmpeg_audio_bitrate*1000; c->channels = 2; codec = avcodec_find_encoder(c->codec_id); if (!codec) { - error("Couldn't find a valid audio codec"); + //XXX error("Couldn't find a valid audio codec"); return NULL; } - set_ffmpeg_properties(c, "audio"); + set_ffmpeg_properties(rd, c, "audio"); if (avcodec_open(c, codec) < 0) { - error("Couldn't initialize audio codec"); + //XXX error("Couldn't initialize audio codec"); return NULL; } @@ -632,7 +630,7 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) do_init_ffmpeg(); /* Determine the correct filename */ - makeffmpegstring(name); + makeffmpegstring(rd, name); fprintf(stderr, "Starting output to %s(ffmpeg)...\n" " Using type=%d, codec=%d, audio_codec=%d,\n" " video_bitrate=%d, audio_bitrate=%d,\n" @@ -646,27 +644,27 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) exts = get_file_extensions(ffmpeg_type); if (!exts) { G.afbreek = 1; /* Abort render */ - error("No valid formats found"); + //XXX error("No valid formats found"); return; } fmt = guess_format(NULL, exts[0], NULL); if (!fmt) { G.afbreek = 1; /* Abort render */ - error("No valid formats found"); + //XXX error("No valid formats found"); return; } of = av_alloc_format_context(); if (!of) { G.afbreek = 1; - error("Error opening output file"); + //XXX error("Error opening output file"); return; } of->oformat = fmt; - of->packet_size= G.scene->r.ffcodecdata.mux_packet_size; + of->packet_size= rd->ffcodecdata.mux_packet_size; if (ffmpeg_multiplex_audio) { - of->mux_rate = G.scene->r.ffcodecdata.mux_rate; + of->mux_rate = rd->ffcodecdata.mux_rate; } else { of->mux_rate = 0; } @@ -709,20 +707,20 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (fmt->video_codec == CODEC_ID_DVVIDEO) { if (rectx != 720) { G.afbreek = 1; - error("Render width has to be 720 pixels for DV!"); + //XXX error("Render width has to be 720 pixels for DV!"); return; } - if (G.scene->r.frs_sec != 25 && recty != 480) { + if (rd->frs_sec != 25 && recty != 480) { G.afbreek = 1; - error("Render height has to be 480 pixels " - "for DV-NTSC!"); + //XXX error("Render height has to be 480 pixels " + // "for DV-NTSC!"); return; } - if (G.scene->r.frs_sec == 25 && recty != 576) { + if (rd->frs_sec == 25 && recty != 576) { G.afbreek = 1; - error("Render height has to be 576 pixels " - "for DV-PAL!"); + //XXX error("Render height has to be 576 pixels " + // "for DV-PAL!"); return; } } @@ -731,40 +729,40 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; - if (ffmpeg_multiplex_audio - && G.scene->audio.mixrate != 48000) { + if (ffmpeg_multiplex_audio && rd->audio.mixrate != 48000) { G.afbreek = 1; - error("FFMPEG only supports 48khz / stereo " - "audio for DV!"); + //XXX error("FFMPEG only supports 48khz / stereo " + // "audio for DV!"); return; } } - video_stream = alloc_video_stream(fmt->video_codec, of, rectx, recty); + video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); if (!video_stream) { G.afbreek = 1; - error("Error initializing video stream"); + //XXX error("Error initializing video stream"); return; } if (ffmpeg_multiplex_audio) { - audio_stream = alloc_audio_stream(fmt->audio_codec, of); + audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); if (!audio_stream) { G.afbreek = 1; - error("Error initializing audio stream"); + //XXX error("Error initializing audio stream"); return; } - audiostream_play(SFRA, 0, 1); + //XXX audiostream_play(SFRA, 0, 1); } if (av_set_parameters(of, NULL) < 0) { G.afbreek = 1; - error("Error setting output parameters"); + //XXX error("Error setting output parameters"); return; } if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&of->pb, name, URL_WRONLY) < 0) { G.afbreek = 1; - error("Could not open file for writing"); + // + //XXX error("Could not open file for writing"); return; } } @@ -779,25 +777,32 @@ void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) ********************************************************************** */ /* Get the output filename-- similar to the other output formats */ -void makeffmpegstring(char* string) { - +static void makeffmpegstring(RenderData* rd, char* string) { + + // XXX quick define, solve! +#define FILE_MAXDIR 256 +#define FILE_MAXFILE 126 + char txt[FILE_MAXDIR+FILE_MAXFILE]; + // XXX +#undef FILE_MAXDIR +#undef FILE_MAXFILE char autosplit[20]; - const char ** exts = get_file_extensions(G.scene->r.ffcodecdata.type); + const char ** exts = get_file_extensions(rd->ffcodecdata.type); const char ** fe = exts; if (!string || !exts) return; - strcpy(string, G.scene->r.pic); + strcpy(string, rd->pic); BLI_convertstringcode(string, G.sce); - BLI_convertstringframe(string, G.scene->r.cfra); + BLI_convertstringframe(string, rd->cfra); BLI_make_existing_file(string); autosplit[0] = 0; - if ((G.scene->r.ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) { + if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) { sprintf(autosplit, "_%03d", ffmpeg_autosplit_count); } @@ -811,8 +816,8 @@ void makeffmpegstring(char* string) { if (!*fe) { strcat(string, autosplit); - sprintf(txt, "%04d_%04d%s", (G.scene->r.sfra), - (G.scene->r.efra), *exts); + sprintf(txt, "%04d_%04d%s", (rd->sfra), + (rd->efra), *exts); strcat(string, txt); } else { *(string + strlen(string) - strlen(*fe)) = 0; @@ -826,8 +831,6 @@ void start_ffmpeg(RenderData *rd, int rectx, int recty) { ffmpeg_autosplit_count = 0; - ffmpeg_renderdata = rd; - start_ffmpeg_impl(rd, rectx, recty); } @@ -853,21 +856,20 @@ static void write_audio_frames() } } -void append_ffmpeg(int frame, int *pixels, int rectx, int recty) +void append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty) { fprintf(stderr, "Writing frame %i, " "render width=%d, render height=%d\n", frame, rectx, recty); write_audio_frames(); - write_video_frame(generate_video_frame((unsigned char*) pixels)); + write_video_frame(rd, generate_video_frame((unsigned char*) pixels)); if (ffmpeg_autosplit) { if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) { end_ffmpeg(); ffmpeg_autosplit_count++; - start_ffmpeg_impl(ffmpeg_renderdata, - rectx, recty); + start_ffmpeg_impl(rd, rectx, recty); } } } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 40e1dc1bb03..2d3a2e6b883 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -47,14 +47,12 @@ #include "BLI_blenlib.h" #include "DNA_userdef_types.h" -#include "BKE_bad_level_calls.h" #include "BKE_global.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "DNA_scene_types.h" -#include "blendef.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -110,14 +108,14 @@ void start_frameserver(RenderData *rd, int rectx, int recty) if (!startup_socket_system()) { G.afbreek = 1; - error("Can't startup socket system"); + //XXX error("Can't startup socket system"); return; } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { shutdown_socket_system(); G.afbreek = 1; /* Abort render */ - error("Can't open socket"); + //XXX error("Can't open socket"); return; } @@ -131,14 +129,14 @@ void start_frameserver(RenderData *rd, int rectx, int recty) if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { shutdown_socket_system(); G.afbreek = 1; /* Abort render */ - error("Can't bind to socket"); + //XXX error("Can't bind to socket"); return; } if (listen(sock, SOMAXCONN) < 0) { shutdown_socket_system(); G.afbreek = 1; /* Abort render */ - error("Can't establish listen backlog"); + //XXX error("Can't establish listen backlog"); return; } connsock = -1; @@ -190,7 +188,7 @@ static int safe_puts(char * s) return safe_write(s, strlen(s)); } -static int handle_request(char * req) +static int handle_request(RenderData *rd, char * req) { char * p; char * path; @@ -232,11 +230,11 @@ static int handle_request(char * req) "height %d\n" "rate %d\n" "ratescale %d\n", - G.scene->r.sfra, - G.scene->r.efra, + rd->sfra, + rd->efra, render_width, render_height, - G.scene->r.frs_sec, + rd->frs_sec, 1 ); @@ -251,7 +249,7 @@ static int handle_request(char * req) return -1; } -int frameserver_loop(void) +int frameserver_loop(RenderData *rd) { fd_set readfds; struct timeval tv; @@ -314,7 +312,7 @@ int frameserver_loop(void) buf[len] = 0; - return handle_request(buf); + return handle_request(rd, buf); } static void serve_ppm(int *pixels, int rectx, int recty) @@ -357,7 +355,7 @@ static void serve_ppm(int *pixels, int rectx, int recty) connsock = -1; } -void append_frameserver(int frame, int *pixels, int rectx, int recty) +void append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty) { fprintf(stderr, "Serving frame: %d\n", frame); if (write_ppm) { |