Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/BME_conversions.c42
-rw-r--r--source/blender/blenkernel/intern/BME_tools.c5
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1138
-rw-r--r--source/blender/blenkernel/intern/Makefile21
-rw-r--r--source/blender/blenkernel/intern/action.c871
-rw-r--r--source/blender/blenkernel/intern/anim.c138
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c899
-rw-r--r--source/blender/blenkernel/intern/armature.c140
-rw-r--r--source/blender/blenkernel/intern/blender.c307
-rw-r--r--source/blender/blenkernel/intern/bmfont.c2
-rw-r--r--source/blender/blenkernel/intern/booleanops.c576
-rw-r--r--source/blender/blenkernel/intern/booleanops_mesh.c293
-rw-r--r--source/blender/blenkernel/intern/brush.c203
-rw-r--r--source/blender/blenkernel/intern/bullet.c1
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c211
-rw-r--r--source/blender/blenkernel/intern/cloth.c18
-rw-r--r--source/blender/blenkernel/intern/collision.c11
-rw-r--r--source/blender/blenkernel/intern/colortools.c36
-rw-r--r--source/blender/blenkernel/intern/constraint.c322
-rw-r--r--source/blender/blenkernel/intern/context.c595
-rw-r--r--source/blender/blenkernel/intern/curve.c97
-rw-r--r--source/blender/blenkernel/intern/customdata.c189
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c217
-rw-r--r--source/blender/blenkernel/intern/displist.c121
-rw-r--r--source/blender/blenkernel/intern/effect.c46
-rw-r--r--source/blender/blenkernel/intern/exotic.c544
-rw-r--r--source/blender/blenkernel/intern/fcurve.c2339
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c11
-rw-r--r--source/blender/blenkernel/intern/font.c290
-rw-r--r--source/blender/blenkernel/intern/gpencil.c516
-rw-r--r--source/blender/blenkernel/intern/group.c12
-rw-r--r--source/blender/blenkernel/intern/idprop.c264
-rw-r--r--source/blender/blenkernel/intern/image.c224
-rw-r--r--source/blender/blenkernel/intern/implicit.c12
-rw-r--r--source/blender/blenkernel/intern/ipo.c3992
-rw-r--r--source/blender/blenkernel/intern/key.c156
-rw-r--r--source/blender/blenkernel/intern/lattice.c121
-rw-r--r--source/blender/blenkernel/intern/library.c187
-rw-r--r--source/blender/blenkernel/intern/material.c17
-rw-r--r--source/blender/blenkernel/intern/mball.c47
-rw-r--r--source/blender/blenkernel/intern/mesh.c130
-rw-r--r--source/blender/blenkernel/intern/modifier.c384
-rw-r--r--source/blender/blenkernel/intern/multires-firstlevel.c409
-rw-r--r--source/blender/blenkernel/intern/multires.c2352
-rw-r--r--source/blender/blenkernel/intern/nla.c6
-rw-r--r--source/blender/blenkernel/intern/node.c376
-rw-r--r--source/blender/blenkernel/intern/object.c437
-rw-r--r--source/blender/blenkernel/intern/packedFile.c19
-rw-r--r--source/blender/blenkernel/intern/particle.c196
-rw-r--r--source/blender/blenkernel/intern/particle_system.c392
-rw-r--r--source/blender/blenkernel/intern/pointcache.c16
-rw-r--r--source/blender/blenkernel/intern/property.c56
-rw-r--r--source/blender/blenkernel/intern/report.c252
-rw-r--r--source/blender/blenkernel/intern/sca.c23
-rw-r--r--source/blender/blenkernel/intern/scene.c249
-rw-r--r--source/blender/blenkernel/intern/screen.c279
-rw-r--r--source/blender/blenkernel/intern/script.c9
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c3155
-rw-r--r--source/blender/blenkernel/intern/sequence.c3417
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c244
-rw-r--r--source/blender/blenkernel/intern/softbody.c165
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c56
-rw-r--r--source/blender/blenkernel/intern/text.c181
-rw-r--r--source/blender/blenkernel/intern/texture.c27
-rw-r--r--source/blender/blenkernel/intern/verse_bitmap_node.c448
-rw-r--r--source/blender/blenkernel/intern/verse_geometry_node.c2098
-rw-r--r--source/blender/blenkernel/intern/verse_method.c520
-rw-r--r--source/blender/blenkernel/intern/verse_node.c747
-rw-r--r--source/blender/blenkernel/intern/verse_object_node.c617
-rw-r--r--source/blender/blenkernel/intern/verse_session.c477
-rw-r--r--source/blender/blenkernel/intern/world.c12
-rw-r--r--source/blender/blenkernel/intern/writeavi.c14
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c172
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c24
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, &timescale);
+ BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
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, &lt->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, &lt->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, &timescale);
+ BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
/* 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) {