soc-2008-mxcurioni: FRS_glBlendEquation files

This commit is contained in:
Maxime Curioni
2008-09-28 18:43:51 +00:00
parent 5812c494a5
commit bb8477ec57
67 changed files with 18788 additions and 17 deletions

View File

@@ -0,0 +1,43 @@
/**
*
* $Id: BKE_bullet.h 16773 2008-09-27 22:01:26Z ben2610 $
*
* ***** 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 *****
*/
#ifndef BKE_BULLET_H
#define BKE_BULLET_H
struct BulletSoftBody;
/* allocates and initializes general main data */
extern struct BulletSoftBody *bsbNew(void);
/* frees internal data and softbody itself */
extern void bsbFree(struct BulletSoftBody *sb);
#endif

View File

@@ -0,0 +1,55 @@
/**
* BKE_fluidsim.h
*
*
* ***** 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 *****
*/
#include "DNA_modifier_types.h"
#include "DNA_object_fluidsim.h" // N_T
#include "DNA_object_types.h"
#include "BKE_DerivedMesh.h"
/* old interface */
FluidsimSettings *fluidsimSettingsNew(Object *srcob);
void initElbeemMesh(Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex);
/* new fluid-modifier interface */
void fluidsim_init(FluidsimModifierData *fluidmd);
void fluidsim_free(FluidsimModifierData *fluidmd);
DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams);
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
// get bounding box of mesh
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] );

View File

@@ -0,0 +1,39 @@
/**
* BKE_shrinkwrap.h
*
* ***** 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 *****
*/
#ifndef BKE_SIMPLE_DEFORM_H
#define BKE_SIMPLE_DEFORM_H
struct Object;
struct DerivedMesh;
struct SimpleDeformModifierData;
void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts);
#endif

View File

@@ -0,0 +1,95 @@
/*
*
* $Id: bullet.c 16776 2008-09-28 03:07:13Z erwin $
*
* ***** 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 *****
*/
#include "MEM_guardedalloc.h"
/* types */
#include "DNA_object_force.h" /* here is the softbody struct */
#include "BKE_bullet.h"
/* ************ Object level, exported functions *************** */
/* allocates and initializes general main data */
BulletSoftBody *bsbNew(void)
{
BulletSoftBody *bsb;
bsb= MEM_callocN(sizeof(BulletSoftBody), "bulletsoftbody");
bsb->flag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT;
bsb->linStiff = 0.5f;
bsb->angStiff = 1.0f;
bsb->volume = 1.0f;
bsb->viterations = 0;
bsb->piterations = 2;
bsb->diterations = 0;
bsb->citerations = 4;
bsb->kSRHR_CL = 0.1f;
bsb->kSKHR_CL = 1.f;
bsb->kSSHR_CL = 0.5f;
bsb->kSR_SPLT_CL = 0.5f;
bsb->kSK_SPLT_CL = 0.5f;
bsb->kSS_SPLT_CL = 0.5f;
bsb->kVCF = 1;
bsb->kDP = 0;
bsb->kDG = 0;
bsb->kLF = 0;
bsb->kPR = 0;
bsb->kVC = 0;
bsb->kDF = 0.2f;
bsb->kMT = 0.05;
bsb->kCHR = 1.0f;
bsb->kKHR = 0.1f;
bsb->kSHR = 1.0f;
bsb->kAHR = 0.7f;
bsb->collisionflags = 0;
//bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS;
bsb->numclusteriterations = 64;
return bsb;
}
/* frees all */
void bsbFree(BulletSoftBody *bsb)
{
/* no internal data yet */
MEM_freeN(bsb);
}

View File

@@ -0,0 +1,642 @@
/**
* fluidsim.c
*
*
* ***** 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 *****
*/
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_force.h" // for pointcache
#include "DNA_particle_types.h"
#include "DNA_scene_types.h" // N_T
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_fluidsim.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_pointcache.h"
#include "BKE_utildefines.h"
// headers for fluidsim bobj meshes
#include <stdlib.h>
#include "LBM_fluidsim.h"
#include "elbeem.h"
#include <zlib.h>
#include <string.h>
#include <stdio.h>
/* ************************* fluidsim bobj file handling **************************** */
// -----------------------------------------
// forward decleration
// -----------------------------------------
// -----------------------------------------
void fluidsim_init(FluidsimModifierData *fluidmd)
{
#ifndef DISABLE_ELBEEM
if(fluidmd)
{
FluidsimSettings *fss = MEM_callocN(sizeof(FluidsimSettings), "fluidsimsettings");
fluidmd->fss = fss;
if(!fss)
return;
fss->type = 0;
fss->show_advancedoptions = 0;
fss->resolutionxyz = 50;
fss->previewresxyz = 25;
fss->realsize = 0.03;
fss->guiDisplayMode = 2; // preview
fss->renderDisplayMode = 3; // render
fss->viscosityMode = 2; // default to water
fss->viscosityValue = 1.0;
fss->viscosityExponent = 6;
// dg TODO: change this to []
fss->gravx = 0.0;
fss->gravy = 0.0;
fss->gravz = -9.81;
fss->animStart = 0.0;
fss->animEnd = 0.30;
fss->gstar = 0.005; // used as normgstar
fss->maxRefine = -1;
// maxRefine is set according to resolutionxyz during bake
// fluid/inflow settings
// fss->iniVel --> automatically set to 0
/* elubie: changed this to default to the same dir as the render output
to prevent saving to C:\ on Windows */
BLI_strncpy(fss->surfdataPath, btempdir, FILE_MAX);
// first init of bounding box
// no bounding box needed
// todo - reuse default init from elbeem!
fss->typeFlags = 0;
fss->domainNovecgen = 0;
fss->volumeInitType = 1; // volume
fss->partSlipValue = 0.0;
fss->generateTracers = 0;
fss->generateParticles = 0.0;
fss->surfaceSmoothing = 1.0;
fss->surfaceSubdivs = 1.0;
fss->particleInfSize = 0.0;
fss->particleInfAlpha = 0.0;
// init fluid control settings
fss->attractforceStrength = 0.2;
fss->attractforceRadius = 0.75;
fss->velocityforceStrength = 0.2;
fss->velocityforceRadius = 0.75;
fss->cpsTimeStart = fss->animStart;
fss->cpsTimeEnd = fss->animEnd;
fss->cpsQuality = 10.0; // 1.0 / 10.0 => means 0.1 width
/*
BAD TODO: this is done in buttons_object.c in the moment
Mesh *mesh = ob->data;
// calculate bounding box
fluid_get_bb(mesh->mvert, mesh->totvert, ob->obmat, fss->bbStart, fss->bbSize);
*/
fss->lastgoodframe = -1;
fss->flag = 0;
}
#endif
return;
}
void fluidsim_free(FluidsimModifierData *fluidmd)
{
#ifndef DISABLE_ELBEEM
if(fluidmd)
{
MEM_freeN(fluidmd->fss);
}
#endif
return;
}
DerivedMesh *fluidsimModifier_do(FluidsimModifierData *fluidmd, 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;
// only handle fluidsim domains
if(fluidmd && fluidmd->fss && (fluidmd->fss->type != OB_FLUIDSIM_DOMAIN))
return dm;
// sanity check
if(!fluidmd || (fluidmd && !fluidmd->fss))
return dm;
fss = fluidmd->fss;
// timescale not supported yet
// clmd->sim_parms->timescale= timescale;
// support reversing of baked fluid frames here
if((fss->flag & OB_FLUIDSIM_REVERSE) && (fss->lastgoodframe >= 0))
{
framenr = fss->lastgoodframe - framenr + 1;
CLAMP(framenr, 1, fss->lastgoodframe);
}
/* try to read from cache */
if(((fss->lastgoodframe >= framenr) || (fss->lastgoodframe < 0)) && (result = fluidsim_read_cache(ob, dm, fluidmd, framenr, useRenderParams)))
{
// fss->lastgoodframe = framenr; // set also in src/fluidsim.c
return result;
}
else
{
// display last known good frame
if(fss->lastgoodframe >= 0)
{
if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
{
return result;
}
// it was supposed to be a valid frame but it isn't!
fss->lastgoodframe = framenr - 1;
// this could be likely the case when you load an old fluidsim
if((result = fluidsim_read_cache(ob, dm, fluidmd, fss->lastgoodframe, useRenderParams)))
{
return result;
}
}
result = CDDM_copy(dm);
if(result)
{
return result;
}
}
return dm;
#else
return NULL;
#endif
}
#ifndef DISABLE_ELBEEM
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
static DerivedMesh *fluidsim_read_obj(char *filename)
{
int wri,i,j;
float wrf;
int gotBytes;
gzFile gzf;
int numverts = 0, numfaces = 0;
DerivedMesh *dm = NULL;
MFace *mface;
MVert *mvert;
short *normals;
// ------------------------------------------------
// get numverts + numfaces first
// ------------------------------------------------
gzf = gzopen(filename, "rb");
if (!gzf)
{
return NULL;
}
// read numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
numverts = wri;
// skip verts
for(i=0; i<numverts*3; i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
}
// read number of normals
gotBytes = gzread(gzf, &wri, sizeof(wri));
// skip normals
for(i=0; i<numverts*3; i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
}
/* get no. of triangles */
gotBytes = gzread(gzf, &wri, sizeof(wri));
numfaces = wri;
gzclose( gzf );
// ------------------------------------------------
if(!numfaces || !numverts)
return NULL;
gzf = gzopen(filename, "rb");
if (!gzf)
{
return NULL;
}
dm = CDDM_new(numverts, 0, numfaces);
if(!dm)
{
gzclose( gzf );
return NULL;
}
// read numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
// read vertex position from file
mvert = CDDM_get_verts(dm);
for(i=0; i<numverts; i++)
{
MVert *mv = &mvert[i];
for(j=0; j<3; j++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
mv->co[j] = wrf;
}
}
// should be the same as numverts
gotBytes = gzread(gzf, &wri, sizeof(wri));
if(wri != numverts)
{
if(dm)
dm->release(dm);
gzclose( gzf );
return NULL;
}
normals = MEM_callocN(sizeof(short) * numverts * 3, "fluid_tmp_normals" );
if(!normals)
{
if(dm)
dm->release(dm);
gzclose( gzf );
return NULL;
}
// read normals from file (but don't save them yet)
for(i=0; i<numverts*3; i++)
{
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
normals[i] = (short)(wrf*32767.0f);
}
/* read no. of triangles */
gotBytes = gzread(gzf, &wri, sizeof(wri));
if(wri!=numfaces)
printf("Fluidsim: error in reading data from file.\n");
// read triangles from file
mface = CDDM_get_faces(dm);
for(i=0; i<numfaces; i++)
{
int face[4];
MFace *mf = &mface[i];
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
face[3] = 0;
// check if 3rd vertex has index 0 (not allowed in blender)
if(face[2])
{
mf->v1 = face[0];
mf->v2 = face[1];
mf->v3 = face[2];
}
else
{
mf->v1 = face[1];
mf->v2 = face[2];
mf->v3 = face[0];
}
mf->v4 = face[3];
test_index_face(mf, NULL, 0, 3);
}
gzclose( gzf );
CDDM_calc_edges(dm);
CDDM_apply_vert_normals(dm, (short (*)[3])normals);
MEM_freeN(normals);
// CDDM_calc_normals(result);
return dm;
}
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 */
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
FluidsimSettings *fss = fluidmd->fss;
DerivedMesh *dm = NULL;
MFace *mface;
int numfaces;
int mat_nr, flag, i;
if(!useRenderParams) {
displaymode = fss->guiDisplayMode;
} else {
displaymode = fss->renderDisplayMode;
}
strncpy(targetDir, fss->surfdataPath, FILE_MAXDIR);
// use preview or final mesh?
if(displaymode==1)
{
// just display original object
return NULL;
}
else if(displaymode==2)
{
strcat(targetDir,"fluidsurface_preview_####");
}
else
{ // 3
strcat(targetDir,"fluidsurface_final_####");
}
BLI_convertstringcode(targetDir, G.sce);
BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no
strcpy(targetFile,targetDir);
strcat(targetFile, ".bobj.gz");
dm = fluidsim_read_obj(targetFile);
if(!dm)
{
// switch, abort background rendering when fluidsim mesh is missing
const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
if(G.background==1) {
if(getenv(strEnvName2)) {
int elevel = atoi(getenv(strEnvName2));
if(elevel>0) {
printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
exit(1);
}
}
}
// display org. object upon failure which is in dm
return NULL;
}
// assign material + flags to new dm
mface = orgdm->getFaceArray(orgdm);
mat_nr = mface[0].mat_nr;
flag = mface[0].flag;
mface = dm->getFaceArray(dm);
numfaces = dm->getNumFaces(dm);
for(i=0; i<numfaces; i++)
{
mface[i].mat_nr = mat_nr;
mface[i].flag = flag;
}
// load vertex velocities, if they exist...
// TODO? use generate flag as loading flag as well?
// warning, needs original .bobj.gz mesh loading filename
/*
if(displaymode==3)
{
readVelgz(targetFile, srcob);
}
else
{
// no data for preview, only clear...
int i,j;
for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }}
}*/
return dm;
}
void fluid_get_bb(MVert *mvert, int totvert, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] )
{
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
float bbex=1.0, bbey=1.0, bbez=1.0;
int i;
float vec[3];
VECCOPY(vec, mvert[0].co);
Mat4MulVecfl(obmat, vec);
bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
for(i = 1; i < totvert; i++) {
VECCOPY(vec, mvert[i].co);
Mat4MulVecfl(obmat, vec);
if(vec[0] < bbsx){ bbsx= vec[0]; }
if(vec[1] < bbsy){ bbsy= vec[1]; }
if(vec[2] < bbsz){ bbsz= vec[2]; }
if(vec[0] > bbex){ bbex= vec[0]; }
if(vec[1] > bbey){ bbey= vec[1]; }
if(vec[2] > bbez){ bbez= vec[2]; }
}
// return values...
if(start) {
start[0] = bbsx;
start[1] = bbsy;
start[2] = bbsz;
}
if(size) {
size[0] = bbex-bbsx;
size[1] = bbey-bbsy;
size[2] = bbez-bbsz;
}
}
//-------------------------------------------------------------------------------
// old interface
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// file handling
//-------------------------------------------------------------------------------
void initElbeemMesh(struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex)
{
DerivedMesh *dm = NULL;
MVert *mvert;
MFace *mface;
int countTris=0, i, totvert, totface;
float *verts;
int *tris;
dm = mesh_create_derived_index_render(ob, CD_MASK_BAREMESH, modifierIndex);
//dm = mesh_create_derived_no_deform(ob,NULL);
mvert = dm->getVertArray(dm);
mface = dm->getFaceArray(dm);
totvert = dm->getNumVerts(dm);
totface = dm->getNumFaces(dm);
*numVertices = totvert;
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
for(i=0; i<totvert; i++) {
VECCOPY( &verts[i*3], mvert[i].co);
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
}
*vertices = verts;
for(i=0; i<totface; i++) {
countTris++;
if(mface[i].v4) { countTris++; }
}
*numTriangles = countTris;
tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
countTris = 0;
for(i=0; i<totface; i++) {
int face[4];
face[0] = mface[i].v1;
face[1] = mface[i].v2;
face[2] = mface[i].v3;
face[3] = mface[i].v4;
tris[countTris*3+0] = face[0];
tris[countTris*3+1] = face[1];
tris[countTris*3+2] = face[2];
countTris++;
if(face[3]) {
tris[countTris*3+0] = face[0];
tris[countTris*3+1] = face[2];
tris[countTris*3+2] = face[3];
countTris++;
}
}
*triangles = tris;
dm->release(dm);
}
/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
void readVelgz(char *filename, Object *srcob)
{
int wri, i, j;
float wrf;
gzFile gzf;
MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
int len = strlen(filename);
Mesh *mesh = srcob->data;
// mesh and vverts have to be valid from loading...
// clean up in any case
for(i=0; i<mesh->totvert;i++)
{
for(j=0; j<3; j++)
{
vverts[i].co[j] = 0.;
}
}
if(srcob->fluidsimSettings->domainNovecgen>0) return;
if(len<7)
{
return;
}
// .bobj.gz , correct filename
// 87654321
filename[len-6] = 'v';
filename[len-5] = 'e';
filename[len-4] = 'l';
gzf = gzopen(filename, "rb");
if (!gzf)
return;
gzread(gzf, &wri, sizeof( wri ));
if(wri != mesh->totvert)
{
return;
}
for(i=0; i<mesh->totvert;i++)
{
for(j=0; j<3; j++)
{
gzread(gzf, &wrf, sizeof( wrf ));
vverts[i].co[j] = wrf;
}
}
gzclose(gzf);
}
#endif // DISABLE_ELBEEM

View File

@@ -0,0 +1,248 @@
/**
* deform_simple.c
*
* ***** 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): André Pinto
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "DNA_object_types.h"
#include "DNA_modifier_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_simple_deform.h"
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
#include "BKE_shrinkwrap.h"
#include <string.h>
#include <math.h>
//Clamps/Limits the given coordinate to: limits[0] <= co[axis] <= limits[1]
//The ammount of clamp is saved on dcut
static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
{
float val = co[axis];
if(limits[0] > val) val = limits[0];
if(limits[1] < val) val = limits[1];
dcut[axis] = co[axis] - val;
co[axis] = val;
}
static void simpleDeform_taper(const float factor, const float dcut[3], float *co)
{
float x = co[0], y = co[1], z = co[2];
float scale = z*factor;
co[0] = x + x*scale;
co[1] = y + y*scale;
co[2] = z;
if(dcut)
{
co[0] += dcut[0];
co[1] += dcut[1];
co[2] += dcut[2];
}
}
static void simpleDeform_stretch(const float factor, const float dcut[3], float *co)
{
float x = co[0], y = co[1], z = co[2];
float scale;
scale = (z*z*factor-factor + 1.0);
co[0] = x*scale;
co[1] = y*scale;
co[2] = z*(1.0+factor);
if(dcut)
{
co[0] += dcut[0];
co[1] += dcut[1];
co[2] += dcut[2];
}
}
static void simpleDeform_twist(const float factor, const float *dcut, float *co)
{
float x = co[0], y = co[1], z = co[2];
float theta, sint, cost;
theta = z*factor;
sint = sin(theta);
cost = cos(theta);
co[0] = x*cost - y*sint;
co[1] = x*sint + y*cost;
co[2] = z;
if(dcut)
{
co[0] += dcut[0];
co[1] += dcut[1];
co[2] += dcut[2];
}
}
static void simpleDeform_bend(const float factor, const float dcut[3], float *co)
{
float x = co[0], y = co[1], z = co[2];
float theta, sint, cost;
theta = x*factor;
sint = sin(theta);
cost = cos(theta);
if(fabs(factor) > 1e-7f)
{
co[0] = -(y-1.0f/factor)*sint;
co[1] = (y-1.0f/factor)*cost + 1.0f/factor;
co[2] = z;
}
if(dcut)
{
co[0] += cost*dcut[0];
co[1] += sint*dcut[0];
co[2] += dcut[2];
}
}
/* simple deform modifier */
void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
static const float lock_axis[2] = {0.0f, 0.0f};
int i;
int limit_axis = 0;
float smd_limit[2], smd_factor;
SpaceTransform *transf = NULL, tmp_transf;
void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback
int vgroup = get_named_vertexgroup_num(ob, smd->vgroup_name);
MDeformVert *dvert = NULL;
//Safe-check
if(smd->origin == ob) smd->origin = NULL; //No self references
if(smd->limit[0] < 0.0) smd->limit[0] = 0.0f;
if(smd->limit[0] > 1.0) smd->limit[0] = 1.0f;
smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit
//Calculate matrixs do convert between coordinate spaces
if(smd->origin)
{
transf = &tmp_transf;
if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL)
{
space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat);
}
else
{
Mat4CpyMat4(transf->local2target, smd->origin->obmat);
Mat4Invert(transf->target2local, transf->local2target);
}
}
//Setup vars
limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z
//Update limits if needed
{
float lower = FLT_MAX;
float upper = -FLT_MAX;
for(i=0; i<numVerts; i++)
{
float tmp[3];
VECCOPY(tmp, vertexCos[i]);
if(transf) space_transform_apply(transf, tmp);
lower = MIN2(lower, tmp[limit_axis]);
upper = MAX2(upper, tmp[limit_axis]);
}
//SMD values are normalized to the BV, calculate the absolut values
smd_limit[1] = lower + (upper-lower)*smd->limit[1];
smd_limit[0] = lower + (upper-lower)*smd->limit[0];
smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]);
}
if(dm)
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
switch(smd->mode)
{
case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break;
case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break;
case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break;
case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break;
default:
return; //No simpledeform mode?
}
for(i=0; i<numVerts; i++)
{
float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup);
if(weight != 0.0f)
{
float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
if(transf) space_transform_apply(transf, vertexCos[i]);
VECCOPY(co, vertexCos[i]);
//Apply axis limits
if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis
{
if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
}
axis_limit(limit_axis, smd_limit, co, dcut);
simpleDeform_callback(smd_factor, dcut, co); //Apply deform
VecLerpf(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation
if(transf) space_transform_invert(transf, vertexCos[i]);
}
}
}

View File

@@ -0,0 +1,9 @@
#include "GLBlendEquation.h"
void FRS_glBlendEquation(GLenum mode) {
if( glBlendEquation ) {
glBlendEquation(mode);
} else if ( glBlendEquationEXT ) {
glBlendEquationEXT(mode);
}
}

View File

@@ -0,0 +1,16 @@
#ifndef GLBLENDEQUATION_H
#define GLBLENDEQUATION_H
#include <GL/glew.h>
#ifdef WIN32
# include <windows.h>
#endif
#ifdef __MACH__
# include <OpenGL/gl.h>
#else
# include <GL/gl.h>
#endif
void FRS_glBlendEquation(GLenum mode);
#endif // GLBLENDEQUATION_H

View File

@@ -0,0 +1,117 @@
/**
* $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z 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 (with some old code)
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef BIF_KEYFRAMING_H
#define BIF_KEYFRAMING_H
struct ListBase;
struct ID;
struct IpoCurve;
struct BezTriple;
/* ************ Keyframing Management **************** */
/* Lesser Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it already
* exists, and there is a beztriple that can be directly copied into the array.
*/
int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt);
/* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will insert a keyframe using the current value being keyframed.
*/
void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag);
/* flags for use in insert_key(), and insert_vert_icu() */
enum {
INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */
INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */
INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */
INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */
INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */
} eInsertKeyFlags;
/* -------- */
/* Main Keyframing API calls:
* Use this to create any necessary animation data,, and then insert a keyframe
* using the current value being keyframed, in the relevant place. Returns success.
*/
// TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil!
short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag);
/* Main Keyframing API call:
* Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case.
*/
short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag);
/* Main Keyframe Management calls:
* These handle keyframes management from various spaces. They will handle the menus
* required for each space.
*/
void common_insertkey(void);
void common_deletekey(void);
/* ************ Auto-Keyframing ********************** */
/* Notes:
* - All the defines for this (User-Pref settings and Per-Scene settings)
* are defined in DNA_userdef_types.h
* - Scene settings take presidence over those for userprefs, with old files
* inheriting userpref settings for the scene settings
* - "On/Off + Mode" are stored per Scene, but "settings" are currently stored
* as userprefs
*/
/* Auto-Keying macros for use by various tools */
/* check if auto-keyframing is enabled (per scene takes presidence) */
#define IS_AUTOKEY_ON ((G.scene) ? (G.scene->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
/* check the mode for auto-keyframing (per scene takes presidence) */
#define IS_AUTOKEY_MODE(mode) ((G.scene) ? (G.scene->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
/* check if a flag is set for auto-keyframing (as userprefs only!) */
#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag)
/* ************ Keyframe Checking ******************** */
/* Checks whether a keyframe exists for the given ID-block one the given frame */
short id_cfra_has_keyframe(struct ID *id, short filter);
/* filter flags fr id_cfra_has_keyframe */
enum {
/* general */
ANIMFILTER_ALL = 0, /* include all available animation data */
ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */
/* object specific */
ANIMFILTER_MAT = (1<<1), /* include material keyframes too */
ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */
} eAnimFilterFlags;
#endif /* BIF_KEYFRAMING_H */

View File

@@ -0,0 +1,1870 @@
/**
* $Id: keyframing.c 14881 2008-05-18 10:41:42Z 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 (with some old code)
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "MEM_guardedalloc.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "DNA_listBase.h"
#include "DNA_ID.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_ipo_types.h"
#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
#include "DNA_material_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
#include "DNA_vec_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_blender.h"
#include "BKE_main.h"
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_ipo.h"
#include "BKE_object.h"
#include "BIF_keyframing.h"
#include "BIF_butspace.h"
#include "BIF_editaction.h"
#include "BIF_editkey.h"
#include "BIF_interface.h"
#include "BIF_mywindow.h"
#include "BIF_poseobject.h"
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BIF_toets.h"
#include "BSE_editipo.h"
#include "BSE_node.h"
#include "BSE_time.h"
#include "BSE_view.h"
#include "blendef.h"
#include "PIL_time.h" /* sleep */
#include "mydevice.h"
/* ************************************************** */
/* LOCAL TYPES AND DEFINES */
/* -------------- Keying Sets ------------------- */
/* keying set - a set of channels that will be keyframed together */
// TODO: move this to a header to allow custom sets someday?
typedef struct bKeyingSet {
/* callback func to consider if keyingset should be included
* (by default, if this is undefined, item will be shown)
*/
short (*include_cb)(struct bKeyingSet *, const char *);
char name[48]; /* name of keyingset */
int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated
short flag; /* flags to use when setting keyframes */
short chan_num; /* number of channels to insert keyframe in */
short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */
} bKeyingSet;
/* keying set context - an array of keying sets and the number of them */
typedef struct bKeyingContext {
bKeyingSet *keyingsets; /* array containing the keyingsets of interest */
bKeyingSet *lastused; /* item that was chosen last time*/
int tot; /* number of keyingsets in */
} bKeyingContext;
/* ----------- Common KeyData Sources ------------ */
/* temporary struct to gather data combos to keyframe */
typedef struct bCommonKeySrc {
struct bCommonKeySrc *next, *prev;
/* general data/destination-source settings */
ID *id; /* id-block this comes from */
char *actname; /* name of action channel */
char *constname; /* name of constraint channel */
/* general destination source settings */
Ipo *ipo; /* ipo-block that id-block has (optional) */
bAction *act; /* action-block that id-block has (optional) */
/* pose-level settings */
bPoseChannel *pchan; /* pose channel */
/* buttons-window settings */
int map; /* offset to apply to certain adrcodes */
} bCommonKeySrc;
/* ************************************************** */
/* KEYFRAME INSERTION */
/* -------------- BezTriple Insertion -------------------- */
/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */
#define BEZT_INSERT_THRESH 0.00001
/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu)
* Returns the index to insert at (data already at that index will be offset if replace is 0)
*/
static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace)
{
int start=0, end=arraylen;
int loopbreaker= 0, maxloop= arraylen * 2;
const float frame= (item)? item->vec[1][0] : 0.0f;
/* initialise replace-flag first */
*replace= 0;
/* sneaky optimisations (don't go through searching process if...):
* - keyframe to be added is to be added out of current bounds
* - keyframe to be added would replace one of the existing ones on bounds
*/
if ((arraylen <= 0) || ELEM(NULL, array, item)) {
printf("Warning: binarysearch_bezt_index encountered invalid array \n");
return 0;
}
else {
/* check whether to add before/after/on */
float framenum;
/* 'First' Keyframe (when only one keyframe, this case is used) */
framenum= array[0].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
*replace = 1;
return 0;
}
else if (frame < framenum)
return 0;
/* 'Last' Keyframe */
framenum= array[(arraylen-1)].vec[1][0];
if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) {
*replace= 1;
return (arraylen - 1);
}
else if (frame > framenum)
return arraylen;
}
/* most of the time, this loop is just to find where to put it
* 'loopbreaker' is just here to prevent infinite loops
*/
for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
/* compute and get midpoint */
int mid = (start + end) / 2;
float midfra= array[mid].vec[1][0];
/* check if exactly equal to midpoint */
if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) {
*replace = 1;
return mid;
}
/* repeat in upper/lower half */
if (frame > midfra)
start= mid + 1;
else if (frame < midfra)
end= mid - 1;
}
/* print error if loop-limit exceeded */
if (loopbreaker == (maxloop-1)) {
printf("Error: binarysearch_bezt_index was taking too long \n");
// include debug info
printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen);
}
/* not found, so return where to place it */
return start;
}
/* This function adds a given BezTriple to an IPO-Curve. It will allocate
* memory for the array if needed, and will insert the BezTriple into a
* suitable place in chronological order.
*
* NOTE: any recalculate of the IPO-Curve that needs to be done will need to
* be done by the caller.
*/
int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt)
{
BezTriple *newb;
int i= 0;
if (icu->bezt == NULL) {
icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
*(icu->bezt)= *bezt;
icu->totvert= 1;
}
else {
short replace = -1;
i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace);
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < icu->totvert))
*(icu->bezt + i) = *bezt;
}
else {
/* add new */
newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple");
/* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
if (i > 0)
memcpy(newb, icu->bezt, i*sizeof(BezTriple));
/* add beztriple to paste at index i */
*(newb + i)= *bezt;
/* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
if (i < icu->totvert)
memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple));
/* replace (+ free) old with new */
MEM_freeN(icu->bezt);
icu->bezt= newb;
icu->totvert++;
}
}
/* we need to return the index, so that some tools which do post-processing can
* detect where we added the BezTriple in the array
*/
return i;
}
/* This function is a wrapper for insert_bezt_icu, and should be used when
* adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
* else yet.
*
* 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
*/
void insert_vert_icu (IpoCurve *icu, float x, float y, short fast)
{
BezTriple beztr;
int a, h1, h2;
/* set all three points, for nicer start position */
memset(&beztr, 0, sizeof(BezTriple));
beztr.vec[0][0]= x;
beztr.vec[0][1]= y;
beztr.vec[1][0]= x;
beztr.vec[1][1]= y;
beztr.vec[2][0]= x;
beztr.vec[2][1]= y;
beztr.hide= IPO_BEZ;
beztr.f1= beztr.f2= beztr.f3= SELECT;
beztr.h1= beztr.h2= HD_AUTO;
/* add temp beztriple to keyframes */
a= insert_bezt_icu(icu, &beztr);
if (!fast) calchandles_ipocurve(icu);
/* set handletype */
if (icu->totvert > 2) {
BezTriple *bezt;
h1= h2= HD_AUTO;
bezt= (icu->bezt + a);
if (a > 0) h1= (bezt-1)->h2;
if (a < icu->totvert-1) h2= (bezt+1)->h1;
bezt->h1= h1;
bezt->h2= h2;
if (!fast) calchandles_ipocurve(icu);
}
}
/* ------------------- Get Data ------------------------ */
/* Get pointer to use to get values from */
// FIXME: this should not be possible with Data-API
static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype)
{
switch (blocktype) {
case ID_PO: /* posechannel */
if (GS(id->name)==ID_OB) {
Object *ob= (Object *)id;
bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
if (pchan) {
*vartype= IPO_FLOAT;
return get_pchan_ipo_poin(pchan, icu->adrcode);
}
}
break;
case ID_CO: /* constraint */
if ((GS(id->name)==ID_OB) && (constname && constname[0])) {
Object *ob= (Object *)id;
bConstraint *con;
/* assume that we only want the influence (as only used for Constraint Channels) */
if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) {
for (con= ob->constraints.first; con; con= con->next) {
if (strcmp(constname, con->name)==0) {
*vartype= IPO_FLOAT;
return &con->enforce;
}
}
}
else if (ob->pose) {
bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
if (pchan) {
for (con= pchan->constraints.first; con; con= con->next) {
if (strcmp(constname, con->name)==0) {
*vartype= IPO_FLOAT;
return &con->enforce;
}
}
}
}
}
break;
case ID_OB: /* object */
/* hack: layer channels for object need to be keyed WITHOUT localview flag...
* tsk... tsk... why must we just dump bitflags upon users :/
*/
if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) {
Object *ob= (Object *)id;
static int layer = 0;
/* init layer to be the object's layer var, then remove local view from it */
layer = ob->lay;
layer &= 0xFFFFFF;
*vartype= IPO_INT_BIT;
/* return pointer to this static var
* - assumes that this pointer won't be stored for use later, so may not be threadsafe
* if multiple keyframe calls are made, but that is unlikely to happen in the near future
*/
return (void *)(&layer);
}
/* no break here for other ob channel-types - as they can be done normally */
default: /* normal data-source */
return get_ipo_poin(id, icu, vartype);
}
/* not valid... */
return NULL;
}
/* -------------- 'Smarter' Keyframing Functions -------------------- */
/* return codes for new_key_needed */
enum {
KEYNEEDED_DONTADD = 0,
KEYNEEDED_JUSTADD,
KEYNEEDED_DELPREV,
KEYNEEDED_DELNEXT
} eKeyNeededStatus;
/* This helper function determines whether a new keyframe is needed */
/* Cases where keyframes should not be added:
* 1. Keyframe to be added bewteen two keyframes with similar values
* 2. Keyframe to be added on frame where two keyframes are already situated
* 3. Keyframe lies at point that intersects the linear line between two keyframes
*/
static short new_key_needed (IpoCurve *icu, float cFrame, float nValue)
{
BezTriple *bezt=NULL, *prev=NULL;
int totCount, i;
float valA = 0.0f, valB = 0.0f;
/* safety checking */
if (icu == NULL) return KEYNEEDED_JUSTADD;
totCount= icu->totvert;
if (totCount == 0) return KEYNEEDED_JUSTADD;
/* loop through checking if any are the same */
bezt= icu->bezt;
for (i=0; i<totCount; i++) {
float prevPosi=0.0f, prevVal=0.0f;
float beztPosi=0.0f, beztVal=0.0f;
/* get current time+value */
beztPosi= bezt->vec[1][0];
beztVal= bezt->vec[1][1];
if (prev) {
/* there is a keyframe before the one currently being examined */
/* get previous time+value */
prevPosi= prev->vec[1][0];
prevVal= prev->vec[1][1];
/* keyframe to be added at point where there are already two similar points? */
if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
return KEYNEEDED_DONTADD;
}
/* keyframe between prev+current points ? */
if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
/* is the value of keyframe to be added the same as keyframes on either side ? */
if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
return KEYNEEDED_DONTADD;
}
else {
float realVal;
/* get real value of curve at that point */
realVal= eval_icu(icu, cFrame);
/* compare whether it's the same as proposed */
if (IS_EQ(realVal, nValue))
return KEYNEEDED_DONTADD;
else
return KEYNEEDED_JUSTADD;
}
}
/* new keyframe before prev beztriple? */
if (cFrame < prevPosi) {
/* A new keyframe will be added. However, whether the previous beztriple
* stays around or not depends on whether the values of previous/current
* beztriples and new keyframe are the same.
*/
if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
return KEYNEEDED_DELNEXT;
else
return KEYNEEDED_JUSTADD;
}
}
else {
/* just add a keyframe if there's only one keyframe
* and the new one occurs before the exisiting one does.
*/
if ((cFrame < beztPosi) && (totCount==1))
return KEYNEEDED_JUSTADD;
}
/* continue. frame to do not yet passed (or other conditions not met) */
if (i < (totCount-1)) {
prev= bezt;
bezt++;
}
else
break;
}
/* Frame in which to add a new-keyframe occurs after all other keys
* -> If there are at least two existing keyframes, then if the values of the
* last two keyframes and the new-keyframe match, the last existing keyframe
* gets deleted as it is no longer required.
* -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last
* keyframe is not equal to last keyframe.
*/
bezt= (icu->bezt + (icu->totvert - 1));
valA= bezt->vec[1][1];
if (prev)
valB= prev->vec[1][1];
else
valB= bezt->vec[1][1] + 1.0f;
if (IS_EQ(valA, nValue) && IS_EQ(valA, valB))
return KEYNEEDED_DELPREV;
else
return KEYNEEDED_JUSTADD;
}
/* ------------------ 'Visual' Keyframing Functions ------------------ */
/* internal status codes for visualkey_can_use */
enum {
VISUALKEY_NONE = 0,
VISUALKEY_LOC,
VISUALKEY_ROT
};
/* This helper function determines if visual-keyframing should be used when
* inserting keyframes for the given channel. As visual-keyframing only works
* on Object and Pose-Channel blocks, this should only get called for those
* blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying
* settings is on.
*/
static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode)
{
Object *ob= NULL;
bConstraint *con= NULL;
short searchtype= VISUALKEY_NONE;
/* validate data */
if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO)))
return 0;
/* get first constraint and determine type of keyframe constraints to check for*/
ob= (Object *)id;
if (blocktype == ID_OB) {
con= ob->constraints.first;
if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z))
searchtype= VISUALKEY_LOC;
else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z))
searchtype= VISUALKEY_ROT;
}
else if (blocktype == ID_PO) {
bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
con= pchan->constraints.first;
if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z))
searchtype= VISUALKEY_LOC;
else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z))
searchtype= VISUALKEY_ROT;
}
/* only search if a searchtype and initial constraint are available */
if (searchtype && con) {
for (; con; con= con->next) {
/* only consider constraint if it is not disabled, and has influence */
if (con->flag & CONSTRAINT_DISABLE) continue;
if (con->enforce == 0.0f) continue;
/* some constraints may alter these transforms */
switch (con->type) {
/* multi-transform constraints */
case CONSTRAINT_TYPE_CHILDOF:
return 1;
case CONSTRAINT_TYPE_TRANSFORM:
return 1;
case CONSTRAINT_TYPE_FOLLOWPATH:
return 1;
/* single-transform constraits */
case CONSTRAINT_TYPE_TRACKTO:
if (searchtype==VISUALKEY_ROT) return 1;
break;
case CONSTRAINT_TYPE_ROTLIMIT:
if (searchtype==VISUALKEY_ROT) return 1;
break;
case CONSTRAINT_TYPE_LOCLIMIT:
if (searchtype==VISUALKEY_LOC) return 1;
break;
case CONSTRAINT_TYPE_ROTLIKE:
if (searchtype==VISUALKEY_ROT) return 1;
break;
case CONSTRAINT_TYPE_DISTLIMIT:
if (searchtype==VISUALKEY_LOC) return 1;
break;
case CONSTRAINT_TYPE_LOCLIKE:
if (searchtype==VISUALKEY_LOC) return 1;
break;
case CONSTRAINT_TYPE_LOCKTRACK:
if (searchtype==VISUALKEY_ROT) return 1;
break;
case CONSTRAINT_TYPE_MINMAX:
if (searchtype==VISUALKEY_LOC) return 1;
break;
default:
break;
}
}
}
/* when some condition is met, this function returns, so here it can be 0 */
return 0;
}
/* This helper function extracts the value to use for visual-keyframing
* In the event that it is not possible to perform visual keying, try to fall-back
* to using the poin method. Assumes that all data it has been passed is valid.
*/
static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu)
{
Object *ob;
void *poin = NULL;
int index, vartype;
/* validate situtation */
if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0))
return 0.0f;
/* get object */
ob= (Object *)id;
/* only valid for objects or posechannels */
if (blocktype == ID_OB) {
/* parented objects are not supported, as the effects of the parent
* are included in the matrix, which kindof beats the point
*/
if (ob->parent == NULL) {
/* only Location or Rotation keyframes are supported now */
if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) {
/* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */
index= adrcode - OB_LOC_X;
return ob->obmat[3][index];
}
else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
float eul[3];
/* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */
index= adrcode - OB_ROT_X;
Mat4ToEul(ob->obmat, eul);
return eul[index]*(5.72958);
}
}
}
else if (blocktype == ID_PO) {
bPoseChannel *pchan;
float tmat[4][4];
/* get data to use */
pchan= get_pose_channel(ob->pose, actname);
/* Although it is not strictly required for this particular space conversion,
* arg1 must not be null, as there is a null check for the other conversions to
* be safe. Therefore, the active object is passed here, and in many cases, this
* will be what owns the pose-channel that is getting this anyway.
*/
Mat4CpyMat4(tmat, pchan->pose_mat);
constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
/* Loc, Rot/Quat keyframes are supported... */
if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) {
/* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */
index= adrcode - AC_LOC_X;
/* only use for non-connected bones */
if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
return tmat[3][index];
else if (pchan->bone->parent == NULL)
return tmat[3][index];
}
else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) {
float trimat[3][3], quat[4];
/* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */
index= adrcode - AC_QUAT_W;
Mat3CpyMat4(trimat, tmat);
Mat3ToQuat_is_ok(trimat, quat);
return quat[index];
}
}
/* as the function hasn't returned yet, try reading from poin */
poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
if (poin)
return read_ipo_poin(poin, vartype);
else
return 0.0;
}
/* ------------------------- Insert Key API ------------------------- */
/* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will insert a keyframe using the current value being keyframed.
*
* The flag argument is used for special settings that alter the behaviour of
* the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
* and extra keyframe filtering.
*/
short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
{
IpoCurve *icu;
/* get ipo-curve */
icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1);
/* only continue if we have an ipo-curve to add keyframe to */
if (icu) {
float cfra = frame_to_float(CFRA);
float curval= 0.0f;
void *poin = NULL;
int vartype;
/* apply special time tweaking */
if (GS(id->name) == ID_OB) {
Object *ob= (Object *)id;
/* apply NLA-scaling (if applicable) */
if (actname && actname[0])
cfra= get_action_frame(ob, cfra);
/* ancient time-offset cruft */
if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
/* actually frametofloat calc again! */
cfra-= give_timeoffset(ob)*G.scene->r.framelen;
}
}
/* get pointer to data to read from */
poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype);
if (poin == NULL) return 0;
/* obtain value to give keyframe */
if ( (flag & INSERTKEY_MATRIX) &&
(visualkey_can_use(id, blocktype, actname, constname, adrcode)) )
{
/* visual-keying is only available for object and pchan datablocks, as
* it works by keyframing using a value extracted from the final matrix
* instead of using the kt system to extract a value.
*/
curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu);
}
else {
/* use kt's read_poin function to extract value (kt->read_poin should
* exist in all cases, but it never hurts to check)
*/
curval= read_ipo_poin(poin, vartype);
}
/* only insert keyframes where they are needed */
if (flag & INSERTKEY_NEEDED) {
short insert_mode;
/* check whether this curve really needs a new keyframe */
insert_mode= new_key_needed(icu, cfra, curval);
/* insert new keyframe at current frame */
if (insert_mode)
insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
/* delete keyframe immediately before/after newly added */
switch (insert_mode) {
case KEYNEEDED_DELPREV:
delete_icu_key(icu, icu->totvert-2, 1);
break;
case KEYNEEDED_DELNEXT:
delete_icu_key(icu, 1, 1);
break;
}
}
else {
/* just insert keyframe */
insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST));
}
/* return success */
return 1;
}
/* return failure */
return 0;
}
/* ************************************************** */
/* KEYFRAME DELETION */
/* Main Keyframing API call:
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will delete a keyframe at the current frame.
*
* The flag argument is used for special settings that alter the behaviour of
* the keyframe deletion. These include the quick refresh options.
*/
short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag)
{
Ipo *ipo;
IpoCurve *icu;
/* get ipo-curve
* Note: here is one of the places where we don't want new ipo + ipo-curve added!
* so 'add' var must be 0
*/
ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0);
icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0);
/* only continue if we have an ipo-curve to remove keyframes from */
if (icu) {
BezTriple bezt;
float cfra = frame_to_float(CFRA);
short found = -1;
int i;
/* apply special time tweaking */
if (GS(id->name) == ID_OB) {
Object *ob= (Object *)id;
/* apply NLA-scaling (if applicable) */
if (actname && actname[0])
cfra= get_action_frame(ob, cfra);
/* ancient time-offset cruft */
if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) {
/* actually frametofloat calc again! */
cfra-= give_timeoffset(ob)*G.scene->r.framelen;
}
}
/* only need to set bezt->vec[1][0], as that's all binarysearch uses */
memset(&bezt, 0, sizeof(BezTriple));
bezt.vec[1][0]= cfra;
/* try to find index of beztriple to get rid of */
i = binarysearch_bezt_index(icu->bezt, &bezt, icu->totvert, &found);
if (found) {
/* delete the key at the index (will sanity check + do recalc afterwards ) */
delete_icu_key(icu, i, 1);
/* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */
if (icu->totvert==0 && icu->driver==NULL) {
BLI_remlink(&ipo->curve, icu);
free_ipo_curve(icu);
}
/* return success */
return 1;
}
}
/* return failure */
return 0;
}
/* ************************************************** */
/* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */
/* ------------- KeyingSet Defines ------------ */
/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */
/* macro for defining keyingset contexts */
#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)}
/* --- */
/* check if option not available for deleting keys */
static short incl_non_del_keys (bKeyingSet *ks, const char mode[])
{
/* as optimisation, assume that it is sufficient to check only first letter
* of mode (int comparison should be faster than string!)
*/
//if (strcmp(mode, "Delete")==0)
if (mode && mode[0]=='D')
return 0;
return 1;
}
/* Object KeyingSets ------ */
/* check if include shapekey entry */
static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[])
{
Object *ob= (G.obedit)? (G.obedit) : (OBACT);
char *newname= NULL;
/* not available for delete mode */
if (strcmp(mode, "Delete")==0)
return 0;
/* check if is geom object that can get shapekeys */
switch (ob->type) {
/* geometry? */
case OB_MESH: newname= "Mesh"; break;
case OB_CURVE: newname= "Curve"; break;
case OB_SURF: newname= "Surface"; break;
case OB_LATTICE: newname= "Lattice"; break;
/* not geometry! */
default:
return 0;
}
/* if ks is shapekey entry (this could be callled for separator before too!) */
if (ks->flag == -3)
sprintf(ks->name, newname);
/* if it gets here, it's ok */
return 1;
}
/* array for object keyingset defines */
bKeyingSet defks_v3d_object[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
{NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
{NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "LocRot", ID_OB, 0, 6,
{OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
{NULL, "LocScale", ID_OB, 0, 6,
{OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
{NULL, "LocRotScale", ID_OB, 0, 9,
{OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
{NULL, "RotScale", ID_OB, 0, 6,
{OB_ROT_X,OB_ROT_Y,OB_ROT_Z,
OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}},
{incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
{incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}},
{incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
{incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6,
{OB_LOC_X,OB_LOC_Y,OB_LOC_Z,
OB_ROT_X,OB_ROT_Y,OB_ROT_Z}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option...
{NULL, "Available", ID_OB, -2, 0, {0}},
{incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry)
{incl_v3d_ob_shapekey, "<ShapeKey>", ID_OB, -3, 0, {0}}
};
/* PoseChannel KeyingSets ------ */
/* array for posechannel keyingset defines */
bKeyingSet defks_v3d_pchan[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
{NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
{NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "LocRot", ID_PO, 0, 7,
{AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,
AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
{NULL, "LocScale", ID_PO, 0, 6,
{AC_LOC_X,AC_LOC_Y,AC_LOC_Z,
AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
{NULL, "LocRotScale", ID_PO, 0, 10,
{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}},
{NULL, "RotScale", ID_PO, 0, 7,
{AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z,
AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}},
{incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator
{incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}},
{incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
{incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7,
{AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,
AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_PO, -2, 0, {0}}
};
/* Material KeyingSets ------ */
/* array for material keyingset defines */
bKeyingSet defks_buts_shading_mat[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}},
{NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}},
{NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}},
{NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "All Color", ID_MA, 0, 18,
{MA_COL_R,MA_COL_G,MA_COL_B,
MA_ALPHA,MA_HASIZE, MA_MODE,
MA_SPEC_R,MA_SPEC_G,MA_SPEC_B,
MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD,
MA_MODE,MA_TRANSLU,MA_ADD}},
{NULL, "All Mirror", ID_MA, 0, 5,
{MA_RAYM,MA_FRESMIR,MA_FRESMIRI,
MA_FRESTRA,MA_FRESTRAI}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
{NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
{NULL, "All Mapping", ID_MA, 0, 14,
{MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
MAP_R,MAP_G,MAP_B,MAP_DVAR,
MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_MA, -2, 0, {0}}
};
/* World KeyingSets ------ */
/* array for world keyingset defines */
bKeyingSet defks_buts_shading_wo[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}},
{NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}},
{NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
{NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
{NULL, "All Mapping", ID_WO, 0, 14,
{MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
MAP_R,MAP_G,MAP_B,MAP_DVAR,
MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_WO, -2, 0, {0}}
};
/* Lamp KeyingSets ------ */
/* array for lamp keyingset defines */
bKeyingSet defks_buts_shading_la[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}},
{NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}},
{NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}},
{NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}},
{NULL, "All Mapping", ID_LA, 0, 14,
{MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z,
MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z,
MAP_R,MAP_G,MAP_B,MAP_DVAR,
MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_LA, -2, 0, {0}}
};
/* Texture KeyingSets ------ */
/* array for texture keyingset defines */
bKeyingSet defks_buts_shading_tex[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "Clouds", ID_TE, 0, 5,
{TE_NSIZE,TE_NDEPTH,TE_NTYPE,
TE_MG_TYP,TE_N_BAS1}},
{NULL, "Marble", ID_TE, 0, 7,
{TE_NSIZE,TE_NDEPTH,TE_NTYPE,
TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
{NULL, "Stucci", ID_TE, 0, 5,
{TE_NSIZE,TE_NTYPE,TE_TURB,
TE_MG_TYP,TE_N_BAS1}},
{NULL, "Wood", ID_TE, 0, 6,
{TE_NSIZE,TE_NTYPE,TE_TURB,
TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}},
{NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}},
{NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}},
{NULL, "Musgrave", ID_TE, 0, 6,
{TE_MG_TYP,TE_MGH,TE_MG_LAC,
TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}},
{NULL, "Voronoi", ID_TE, 0, 9,
{TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4,
TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT,
TE_ISCA,TE_NSIZE}},
{NULL, "Distorted Noise", ID_TE, 0, 4,
{TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}},
{NULL, "Color Filter", ID_TE, 0, 5,
{TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_TE, -2, 0, {0}}
};
/* Object Buttons KeyingSets ------ */
/* check if include particles entry */
static short incl_buts_ob (bKeyingSet *ks, const char mode[])
{
Object *ob= OBACT;
/* only if object is mesh type */
return (ob->type == OB_MESH);
}
/* array for texture keyingset defines */
bKeyingSet defks_buts_object[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}},
{incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}},
{incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}},
{NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too!
};
/* Camera Buttons KeyingSets ------ */
/* check if include internal-renderer entry */
static short incl_buts_cam1 (bKeyingSet *ks, const char mode[])
{
/* only if renderer is internal renderer */
return (G.scene->r.renderer==R_INTERN);
}
/* check if include external-renderer entry */
static short incl_buts_cam2 (bKeyingSet *ks, const char mode[])
{
/* only if renderer is internal renderer */
return (G.scene->r.renderer!=R_INTERN);
}
/* array for camera keyingset defines */
bKeyingSet defks_buts_cam[] =
{
/* include_cb, name, blocktype, flag, chan_num, adrcodes */
{NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}},
{NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}},
{NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}},
{incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}},
{NULL, "%l", 0, -1, 0, {0}}, // separator
{NULL, "Available", ID_CA, -2, 0, {0}}
};
/* --- */
/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */
bKeyingContext ks_contexts[] =
{
KSC_TEMPLATE(v3d_object),
KSC_TEMPLATE(v3d_pchan),
KSC_TEMPLATE(buts_shading_mat),
KSC_TEMPLATE(buts_shading_wo),
KSC_TEMPLATE(buts_shading_la),
KSC_TEMPLATE(buts_shading_tex),
KSC_TEMPLATE(buts_object),
KSC_TEMPLATE(buts_cam)
};
/* Keying Context Enumeration - Must keep in sync with definitions*/
typedef enum eKS_Contexts {
KSC_V3D_OBJECT = 0,
KSC_V3D_PCHAN,
KSC_BUTS_MAT,
KSC_BUTS_WO,
KSC_BUTS_LA,
KSC_BUTS_TEX,
KSC_BUTS_OB,
KSC_BUTS_CAM,
/* make sure this last one remains untouched! */
KSC_TOT_TYPES
} eKS_Contexts;
/* ---------------- KeyingSet Tools ------------------- */
/* helper for commonkey_context_get() - get keyingsets for 3d-view */
static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc)
{
Object *ob;
IpoCurve *icu;
if ((OBACT) && (OBACT->flag & OB_POSEMODE)) {
bPoseChannel *pchan;
/* pose-level */
ob= OBACT;
*ksc= &ks_contexts[KSC_V3D_PCHAN];
set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */
/* loop through posechannels */
for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
if (pchan->flag & POSE_KEY) {
bCommonKeySrc *cks;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set id-block to key to, and action */
cks->id= (ID *)ob;
cks->act= ob->action;
/* set pchan */
cks->pchan= pchan;
cks->actname= pchan->name;
}
}
}
else {
Base *base;
/* object-level */
*ksc= &ks_contexts[KSC_V3D_OBJECT];
/* loop through bases */
for (base= FIRSTBASE; base; base= base->next) {
if (TESTBASELIB(base)) {
bCommonKeySrc *cks;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set id-block to key to */
ob= base->object;
cks->id= (ID *)ob;
/* when ob's keyframes are in an action, default to using 'Object' as achan name */
if (ob->ipoflag & OB_ACTION_OB)
cks->actname= "Object";
/* set ipo-flags */
// TODO: add checks for lib-linked data
if ((ob->ipo) || (ob->action)) {
if (ob->ipo) {
cks->ipo= ob->ipo;
}
else {
bActionChannel *achan;
cks->act= ob->action;
achan= get_action_channel(ob->action, cks->actname);
if (achan && achan->ipo)
cks->ipo= achan->ipo;
}
/* deselect all ipo-curves */
for (icu= cks->ipo->curve.first; icu; icu= icu->next) {
icu->flag &= ~IPO_SELECT;
}
}
}
}
}
}
/* helper for commonkey_context_get() - get keyingsets for buttons window */
static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc)
{
bCommonKeySrc *cks;
/* check on tab-type */
switch (G.buts->mainb) {
case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */
/* subtabs include "Material", "Texture", "Lamp", "World"*/
switch (G.buts->tab[CONTEXT_SHADING]) {
case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */
{
Material *ma= editnode_get_active_material(G.buts->lockpoin);
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set data */
cks->id= (ID *)ma;
cks->ipo= ma->ipo;
cks->map= texchannel_to_adrcode(ma->texact);
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_MAT];
return;
}
break;
case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */
{
World *wo= G.buts->lockpoin;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set data */
cks->id= (ID *)wo;
cks->ipo= wo->ipo;
cks->map= texchannel_to_adrcode(wo->texact);
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_WO];
return;
}
break;
case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */
{
Lamp *la= G.buts->lockpoin;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set data */
cks->id= (ID *)la;
cks->ipo= la->ipo;
cks->map= texchannel_to_adrcode(la->texact);
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_LA];
return;
}
break;
case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */
{
Tex *tex= G.buts->lockpoin;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set data */
cks->id= (ID *)tex;
cks->ipo= tex->ipo;
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_TEX];
return;
}
break;
}
break;
case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */
{
Object *ob= OBACT;
if (ob) {
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set id-block to key to */
cks->id= (ID *)ob;
cks->ipo= ob->ipo;
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_OB];
return;
}
}
break;
case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */
{
Object *ob= OBACT;
if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */
Camera *ca= G.buts->lockpoin;
/* add new keyframing destination */
cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc");
BLI_addtail(sources, cks);
/* set id-block to key to */
cks->id= (ID *)ca;
cks->ipo= ca->ipo;
/* set keyingsets */
*ksc= &ks_contexts[KSC_BUTS_CAM];
return;
}
}
break;
}
/* if nothing happened... */
*ksc= NULL;
}
/* get keyingsets for appropriate context */
static void commonkey_context_get (ScrArea *sa, ListBase *sources, bKeyingContext **ksc)
{
/* check view type */
switch (sa->spacetype) {
/* 3d view - first one tested as most often used */
case SPACE_VIEW3D:
{
commonkey_context_getv3d(sources, ksc);
}
break;
/* buttons view */
case SPACE_BUTS:
{
commonkey_context_getsbuts(sources, ksc);
}
break;
/* timeline view - keyframe buttons */
case SPACE_TIME:
{
ScrArea *sab;
/* try to find largest 3d-view available
* (mostly of the time, this is what when user will want this,
* as it's a standard feature in all other apps)
*/
sab= find_biggest_area_of_type(SPACE_VIEW3D);
if (sab) {
commonkey_context_getv3d(sources, ksc);
return;
}
/* otherwise, try to find the biggest area
* WARNING: must check if that area is another timeline, as that would cause infinite loop
*/
sab= closest_bigger_area();
if ((sab) && (sab->spacetype != SPACE_TIME))
commonkey_context_get(sab, sources, ksc);
}
break;
}
}
/* flush updates after all operations */
static void commonkey_context_finish (ListBase *sources)
{
/* check view type */
switch (curarea->spacetype) {
/* 3d view - first one tested as most often used */
case SPACE_VIEW3D:
{
/* either pose or object level */
if (OBACT && (OBACT->pose)) {
Object *ob= OBACT;
/* recalculate ipo handles, etc. */
if (ob->action)
remake_action_ipos(ob->action);
/* recalculate bone-paths on adding new keyframe? */
// TODO: currently, there is no setting to turn this on/off globally
if (ob->pose->flag & POSE_RECALCPATHS)
pose_recalculate_paths(ob);
}
else {
bCommonKeySrc *cks;
/* loop over bases (as seen in sources) */
for (cks= sources->first; cks; cks= cks->next) {
Object *ob= (Object *)cks->id;
/* simply set recalc flag */
ob->recalc |= OB_RECALC_OB;
}
}
}
break;
}
}
/* flush refreshes after undo */
static void commonkey_context_refresh (void)
{
/* check view type */
switch (curarea->spacetype) {
/* 3d view - first one tested as most often used */
case SPACE_VIEW3D:
{
/* do refreshes */
DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
allspace(REMAKEIPO, 0);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWMARKER, 0);
}
break;
}
}
/* --- */
/* Build menu-string of available keying-sets (allocates memory for string)
* NOTE: mode must not be longer than 64 chars
*/
static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48])
{
DynStr *pupds= BLI_dynstr_new();
bKeyingSet *ks;
char buf[64];
char *str;
int i, n;
/* add title first */
BLI_snprintf(buf, 64, "%s Key %%t|", mode);
BLI_dynstr_append(pupds, buf);
/* loop through keyingsets, adding them */
for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) {
/* check if keyingset can be used */
if (ks->flag == -1) {
/* optional separator? */
if (ks->include_cb) {
if (ks->include_cb(ks, mode)) {
BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") );
BLI_dynstr_append(pupds, buf);
}
}
else {
BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") );
BLI_dynstr_append(pupds, buf);
}
}
else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) {
/* entry can be included */
BLI_dynstr_append(pupds, ks->name);
/* check if special "shapekey" entry */
if (ks->flag == -3)
BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") );
else
BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") );
BLI_dynstr_append(pupds, buf);
}
}
/* convert to normal MEM_malloc'd string */
str= BLI_dynstr_get_cstring(pupds);
BLI_dynstr_free(pupds);
return str;
}
/* Get the keying set that was chosen by the user from the menu */
static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index)
{
/* check if index is valid */
if (ELEM(NULL, ksc, ksc->keyingsets))
return NULL;
if ((index < 1) || (index > ksc->tot))
return NULL;
/* index starts from 1, and should directly correspond to keyingset in array */
return (bKeyingSet *)(ksc->keyingsets + (index - 1));
}
/* ---------------- Keyframe Management API -------------------- */
/* mode for common_modifykey */
enum {
COMMONKEY_MODE_INSERT = 0,
COMMONKEY_MODE_DELETE,
} eCommonModifyKey_Modes;
/* Display a menu for handling the insertion of keyframes based on the active view */
// TODO: add back an option for repeating last keytype
void common_modifykey (short mode)
{
ListBase dsources = {NULL, NULL};
bKeyingContext *ksc= NULL;
bCommonKeySrc *cks;
bKeyingSet *ks = NULL;
char *menustr, buf[64];
short menu_nr;
/* check if mode is valid */
if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0)
return;
/* delegate to other functions or get keyingsets to use */
switch (curarea->spacetype) {
/* spaces with their own methods */
case SPACE_IPO:
if (mode == COMMONKEY_MODE_INSERT)
insertkey_editipo();
return;
case SPACE_ACTION:
if (mode == COMMONKEY_MODE_INSERT)
insertkey_action();
return;
/* TODO: based on UI elements? will that even be handled here??? */
/* default - check per view */
default:
/* get the keyingsets and the data to add keyframes to */
commonkey_context_get(curarea, &dsources, &ksc);
break;
}
/* check that there is data to operate on */
if (ELEM(NULL, dsources.first, ksc)) {
BLI_freelistN(&dsources);
return;
}
/* get menu and process it */
if (mode == COMMONKEY_MODE_DELETE)
menustr= build_keyingsets_menu(ksc, "Delete");
else
menustr= build_keyingsets_menu(ksc, "Insert");
menu_nr= pupmenu(menustr);
if (menustr) MEM_freeN(menustr);
/* no item selected or shapekey entry? */
if (menu_nr < 1) {
/* free temp sources */
BLI_freelistN(&dsources);
/* check if insert new shapekey */
if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT))
insert_shapekey(OBACT);
else
ksc->lastused= NULL;
return;
}
else {
/* try to get keyingset */
ks= get_keyingset_fromcontext(ksc, menu_nr);
if (ks == NULL) {
BLI_freelistN(&dsources);
return;
}
}
/* loop over each destination, applying the keying set */
for (cks= dsources.first; cks; cks= cks->next) {
short success= 0;
/* special hacks for 'available' option */
if (ks->flag == -2) {
IpoCurve *icu= NULL, *icn= NULL;
/* get first IPO-curve */
if (cks->act && cks->actname) {
bActionChannel *achan= get_action_channel(cks->act, cks->actname);
// FIXME: what about constraint channels?
if (achan && achan->ipo)
icu= achan->ipo->curve.first;
}
else
icu= cks->ipo->curve.first;
/* we get adrcodes directly from IPO curves (see method below...) */
for (; icu; icu= icn) {
short flag;
/* get next ipo-curve in case current is deleted */
icn= icu->next;
/* insert mode or delete mode */
if (mode == COMMONKEY_MODE_DELETE) {
/* local flags only add on to global flags */
flag = 0;
/* delete keyframe */
success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
}
else {
/* local flags only add on to global flags */
flag = ks->flag;
if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
// if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
/* insert keyframe */
success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag);
}
}
}
else {
int i;
/* loop over channels available in keyingset */
for (i=0; i < ks->chan_num; i++) {
short flag, adrcode;
/* get adrcode
* - certain adrcodes (for MTEX channels need special offsets) // BAD CRUFT!!!
*/
adrcode= ks->adrcodes[i];
if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) {
switch (adrcode) {
case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z:
case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z:
case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR:
case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP:
adrcode += cks->map;
break;
}
}
/* insert mode or delete mode */
if (mode == COMMONKEY_MODE_DELETE) {
/* local flags only add on to global flags */
flag = 0;
/* delete keyframe */
success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
}
else {
/* local flags only add on to global flags */
flag = ks->flag;
if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX;
if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED;
// if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE;
/* insert keyframe */
success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag);
}
}
}
/* special handling for some key-sources */
if (success) {
/* set pose recalc-paths flag */
if (cks->pchan) {
Object *ob= (Object *)cks->id;
bPoseChannel *pchan= cks->pchan;
/* set flag to trigger path recalc */
if (pchan->path)
ob->pose->flag |= POSE_RECALCPATHS;
/* clear unkeyed flag (it doesn't matter if it's set or not) */
if (pchan->bone)
pchan->bone->flag &= ~BONE_UNKEYED;
}
}
}
/* apply post-keying flushes for this data sources */
commonkey_context_finish(&dsources);
ksc->lastused= ks;
/* free temp data */
BLI_freelistN(&dsources);
/* undo pushes */
if (mode == COMMONKEY_MODE_DELETE)
BLI_snprintf(buf, 64, "Delete %s Key", ks->name);
else
BLI_snprintf(buf, 64, "Insert %s Key", ks->name);
BIF_undo_push(buf);
/* queue updates for contexts */
commonkey_context_refresh();
}
/* ---- */
/* used to insert keyframes from any view */
void common_insertkey (void)
{
common_modifykey(COMMONKEY_MODE_INSERT);
}
/* used to insert keyframes from any view */
void common_deletekey (void)
{
common_modifykey(COMMONKEY_MODE_DELETE);
}
/* ************************************************** */