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/ipo.c')
-rw-r--r--source/blender/blenkernel/intern/ipo.c3737
1 files changed, 2056 insertions, 1681 deletions
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 59eb3837aab..29db0ddd808 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -23,7 +23,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): 2008, Joshua Leung (IPO System cleanup)
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -73,15 +73,23 @@
#include "BKE_main.h"
#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
};
@@ -151,9 +159,9 @@ int wo_ar[WO_TOTIPO]= {
};
int la_ar[LA_TOTIPO]= {
- LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B,
+ LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B,
LA_DIST, LA_SPOTSI, LA_SPOTBL,
- LA_QUAD1, LA_QUAD2, LA_HALOINT,
+ 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,
@@ -175,460 +183,617 @@ 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_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_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD
};
+/* ************************** Data-Level Functions ************************* */
+
+/* ---------------------- Freeing --------------------------- */
-float frame_to_float(int cfra) /* see also bsystem_time in object.c */
+/* frees the ipo curve itself too */
+void free_ipo_curve (IpoCurve *icu)
{
- extern float bluroffs; /* bad stuff borrowed from object.c */
- extern float fieldoffs;
- float ctime;
+ if (icu == NULL)
+ return;
- ctime= (float)cfra;
- ctime+= bluroffs+fieldoffs;
- ctime*= G.scene->r.framelen;
+ if (icu->bezt)
+ MEM_freeN(icu->bezt);
+ if (icu->driver)
+ MEM_freeN(icu->driver);
- return ctime;
-}
-
-/* includes ipo curve itself */
-void free_ipo_curve(IpoCurve *icu)
-{
- if(icu->bezt) MEM_freeN(icu->bezt);
- if(icu->bp) MEM_freeN(icu->bp);
- if(icu->driver) MEM_freeN(icu->driver);
MEM_freeN(icu);
}
/* do not free ipo itself */
-void free_ipo(Ipo *ipo)
+void free_ipo (Ipo *ipo)
{
- IpoCurve *icu;
+ IpoCurve *icu, *icn;
+
+ if (ipo == NULL)
+ return;
- while( (icu= ipo->curve.first) ) {
+ for (icu= ipo->curve.first; icu; icu= icn) {
+ icn= icu->next;
+
+ /* must remove the link before freeing, as the curve is freed too */
BLI_remlink(&ipo->curve, icu);
free_ipo_curve(icu);
}
}
+/* ---------------------- Init --------------------------- */
+
/* on adding new ipos, or for empty views */
-void ipo_default_v2d_cur(int blocktype, rctf *cur)
+void ipo_default_v2d_cur (int blocktype, rctf *cur)
{
- if(blocktype==ID_CA) {
- cur->xmin= G.scene->r.sfra;
- cur->xmax= G.scene->r.efra;
- cur->ymin= 0.0;
- cur->ymax= 100.0;
- }
- else if ELEM5(blocktype, ID_MA, ID_CU, ID_WO, ID_LA, ID_CO) {
- cur->xmin= (float)G.scene->r.sfra-0.1;
- cur->xmax= G.scene->r.efra;
- cur->ymin= (float)-0.1;
- cur->ymax= (float)+1.1;
- }
- else if(blocktype==ID_TE) {
- cur->xmin= (float)G.scene->r.sfra-0.1;
- cur->xmax= G.scene->r.efra;
- cur->ymin= (float)-0.1;
- cur->ymax= (float)+1.1;
- }
- else if(blocktype==ID_SEQ) {
- cur->xmin= -5.0;
- cur->xmax= 105.0;
- cur->ymin= (float)-0.1;
- cur->ymax= (float)+1.1;
- }
- else if(blocktype==ID_KE) {
- cur->xmin= (float)G.scene->r.sfra-0.1;
- cur->xmax= G.scene->r.efra;
- cur->ymin= (float)-0.1;
- cur->ymax= (float)+2.1;
- }
- else { /* ID_OB and everything else */
- cur->xmin= G.scene->r.sfra;
- cur->xmax= G.scene->r.efra;
- cur->ymin= -5.0;
- cur->ymax= +5.0;
+ 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;
}
}
-
-Ipo *add_ipo(char *name, int idcode)
+/* create a new IPO block (allocates the block) */
+Ipo *add_ipo (char name[], int blocktype)
{
Ipo *ipo;
ipo= alloc_libblock(&G.main->ipo, ID_IP, name);
- ipo->blocktype= idcode;
- ipo_default_v2d_cur(idcode, &ipo->cur);
+ ipo->blocktype= blocktype;
+ ipo_default_v2d_cur(blocktype, &ipo->cur);
return ipo;
}
-Ipo *copy_ipo(Ipo *ipo)
+/* ---------------------- Copy --------------------------- */
+
+/* duplicate an IPO block and all its data */
+Ipo *copy_ipo (Ipo *src)
{
- Ipo *ipon;
+ Ipo *dst;
IpoCurve *icu;
- if(ipo==NULL) return 0;
-
- ipon= copy_libblock(ipo);
+ if (src == NULL)
+ return NULL;
- duplicatelist(&(ipon->curve), &(ipo->curve));
+ dst= copy_libblock(src);
+ duplicatelist(&dst->curve, &src->curve);
- for(icu= ipo->curve.first; icu; icu= icu->next) {
+ for (icu= src->curve.first; icu; icu= icu->next) {
icu->bezt= MEM_dupallocN(icu->bezt);
- if(icu->driver) icu->driver= MEM_dupallocN(icu->driver);
+
+ if (icu->driver)
+ icu->driver= MEM_dupallocN(icu->driver);
}
- return ipon;
+ return dst;
}
-/* uses id->newid to match pointers with other copied data */
-void ipo_idnew(Ipo *ipo)
+/* ---------------------- Relink --------------------------- */
+
+/* uses id->newid to match pointers with other copied data
+ * - called after single-user or other such
+ */
+void ipo_idnew (Ipo *ipo)
{
- if(ipo) {
+ if (ipo) {
IpoCurve *icu;
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->driver) {
+ for (icu= ipo->curve.first; icu; icu= icu->next) {
+ if (icu->driver)
ID_NEW(icu->driver->ob);
- }
}
}
}
-void make_local_obipo(Ipo *ipo)
+/* --------------------- Find + Check ----------------------- */
+
+/* find the IPO-curve within a given IPO-block with the adrcode of interest */
+IpoCurve *find_ipocurve (Ipo *ipo, int adrcode)
+{
+ if (ipo) {
+ IpoCurve *icu;
+
+ for (icu= ipo->curve.first; icu; icu= icu->next) {
+ if (icu->adrcode == adrcode)
+ return icu;
+ }
+ }
+ return NULL;
+}
+
+/* return whether the given IPO block has a IPO-curve with the given adrcode */
+short has_ipo_code(Ipo *ipo, int adrcode)
+{
+ /* 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 *ipon;
+ Ipo *dst;
int local=0, lib=0;
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
-
- ob= G.main->object.first;
- while(ob) {
- if(ob->ipo==ipo) {
- if(ob->id.lib) lib= 1;
+ /* 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;
}
- ob= ob->id.next;
}
- if(local && lib==0) {
- ipo->id.lib= 0;
- ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ipo, 0);
+ /* only local - set flag */
+ if (local && lib==0) {
+ src->id.lib= 0;
+ src->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)src, 0);
}
- else if(local && lib) {
- ipon= copy_ipo(ipo);
- ipon->id.us= 0;
+ /* mixed: make copy */
+ else if (local && lib) {
+ dst= copy_ipo(src);
+ dst->id.us= 0;
- ob= G.main->object.first;
- while(ob) {
- if(ob->ipo==ipo) {
-
- if(ob->id.lib==NULL) {
- ob->ipo= ipon;
- ipon->id.us++;
- ipo->id.us--;
+ 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--;
}
}
- ob= ob->id.next;
}
}
}
-void make_local_matipo(Ipo *ipo)
+/* make the given IPO local (for Materials)
+ * - only lib users: do nothing
+ * - only local users: set flag
+ * - mixed: make copy
+ */
+void make_local_matipo (Ipo *src)
{
Material *ma;
- Ipo *ipon;
+ Ipo *dst;
int local=0, lib=0;
-
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
- ma= G.main->mat.first;
- while(ma) {
- if(ma->ipo==ipo) {
- if(ma->id.lib) lib= 1;
+ /* 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;
}
- ma= ma->id.next;
}
- if(local && lib==0) {
- ipo->id.lib= 0;
- ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ipo, 0);
+ /* only local - set flag */
+ if (local && lib==0) {
+ src->id.lib= 0;
+ src->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)src, 0);
}
- else if(local && lib) {
- ipon= copy_ipo(ipo);
- ipon->id.us= 0;
+ /* mixed: make copy */
+ else if (local && lib) {
+ dst= copy_ipo(src);
+ dst->id.us= 0;
- ma= G.main->mat.first;
- while(ma) {
- if(ma->ipo==ipo) {
-
- if(ma->id.lib==NULL) {
- ma->ipo= ipon;
- ipon->id.us++;
- ipo->id.us--;
+ 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--;
}
}
- ma= ma->id.next;
}
}
}
-void make_local_keyipo(Ipo *ipo)
+/* 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)
{
Key *key;
- Ipo *ipon;
+ Ipo *dst;
int local=0, lib=0;
-
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
- key= G.main->key.first;
- while(key) {
- if(key->ipo==ipo) {
- if(key->id.lib) lib= 1;
+ /* 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;
}
- key= key->id.next;
}
- if(local && lib==0) {
- ipo->id.lib= 0;
- ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)ipo, 0);
+ /* only local - set flag */
+ if (local && lib==0) {
+ src->id.lib= 0;
+ src->id.flag= LIB_LOCAL;
+ new_id(0, (ID *)src, 0);
}
- else if(local && lib) {
- ipon= copy_ipo(ipo);
- ipon->id.us= 0;
+ /* mixed: make copy */
+ else if (local && lib) {
+ dst= copy_ipo(src);
+ dst->id.us= 0;
- key= G.main->key.first;
- while(key) {
- if(key->ipo==ipo) {
-
- if(key->id.lib==NULL) {
- key->ipo= ipon;
- ipon->id.us++;
- ipo->id.us--;
+ 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--;
}
}
- key= key->id.next;
}
}
}
-void make_local_ipo(Ipo *ipo)
+/* generic call to make IPO's local */
+void make_local_ipo (Ipo *ipo)
{
-
- if(ipo->id.lib==NULL) return;
- if(ipo->id.us==1) {
+ /* 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;
}
- if(ipo->blocktype==ID_OB) make_local_obipo(ipo);
- else if(ipo->blocktype==ID_MA) make_local_matipo(ipo);
- else if(ipo->blocktype==ID_KE) make_local_keyipo(ipo);
-
+ /* when more than 1 user, can only make local for certain blocktypes */
+ switch (ipo->blocktype) {
+ case ID_OB:
+ make_local_obipo(ipo);
+ break;
+ case ID_MA:
+ make_local_matipo(ipo);
+ break;
+ case ID_KE:
+ make_local_keyipo(ipo);
+ break;
+ }
}
-IpoCurve *find_ipocurve(Ipo *ipo, int adrcode)
+/* ***************************** Keyframe Column Tools ********************************* */
+
+/* add a BezTriple to a column */
+void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
{
- if(ipo) {
- IpoCurve *icu;
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->adrcode==adrcode) return icu;
+ 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;
}
- return NULL;
+
+ /* 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;
}
-void calchandles_ipocurve(IpoCurve *icu)
+/* make a list of keyframe 'columns' in an IPO block */
+void make_cfra_list (Ipo *ipo, ListBase *elems)
{
- BezTriple *bezt, *prev, *next;
+ 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?)
+ */
+
+ bezt= icu->bezt;
+ if (bezt) {
+ for (a=0; a < icu->totvert; a++, bezt++) {
+ add_to_cfra_elem(elems, bezt);
+ }
+ }
+ }
+ }
+}
+
+/* ***************************** Timing Stuff ********************************* */
- a= icu->totvert;
+/* 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;
- /* IPO_CONST doesn't have handles */
- if(a<2 || icu->ipo==IPO_CONST) return;
+ ctime= (float)cfra;
+ ctime+= bluroffs+fieldoffs;
+ ctime*= G.scene->r.framelen;
- bezt= icu->bezt;
- prev= 0;
- next= bezt+1;
+ return ctime;
+}
- while(a--) {
+/* ***************************** 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
+ */
- 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 recalculates the handles of an IPO-Curve
+ * If the BezTriples have been rearranged, sort them first before using this.
+ */
+void calchandles_ipocurve (IpoCurve *icu)
+{
+ BezTriple *bezt, *prev, *next;
+ int a= icu->totvert;
- if(icu->flag & IPO_AUTO_HORIZ)
+ /* 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);
+
+ /* 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 */
-
- prev= bezt;
- if(a==1) {
- next= 0;
- }
- else next++;
-
+
/* for automatic ease in and out */
- if(bezt->h1==HD_AUTO && bezt->h2==HD_AUTO) {
- if(a==0 || a==icu->totvert-1) {
- if(icu->extrap==IPO_HORIZ) {
+ 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];
}
}
}
+ /* advance pointers for next iteration */
+ prev= bezt;
+ if (a == 1) next= NULL;
+ else next++;
bezt++;
}
}
-void testhandles_ipocurve(IpoCurve *icu)
+/* 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)
{
- /* use when something has changed with handles.
- 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
- */
- BezTriple *bezt;
- int flag, a;
+ BezTriple *bezt;
+ int a;
- bezt= icu->bezt;
- if(bezt==NULL) return;
+ /* only beztriples have handles (bpoints don't though) */
+ if (ELEM(NULL, icu, icu->bezt))
+ return;
- a= icu->totvert;
- while(a--) {
- flag= 0;
- if(bezt->f1 & SELECT) flag++;
- if(bezt->f2 & SELECT) flag += 2;
- if(bezt->f3 & SELECT) flag += 4;
-
- if( !(flag==0 || flag==7) ) {
- if(bezt->h1==HD_AUTO) { /* auto */
+ /* 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) { /* auto */
+ 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->h1==HD_VECT) { /* vector */
- if(flag < 4) bezt->h1= 0;
- }
- if(bezt->h2==HD_VECT) { /* vector */
- if( flag > 3) bezt->h2= 0;
+ if(bezt->h2==HD_VECT) {
+ /* only right half (4 or 2+4) */
+ if (flag > 3)
+ bezt->h2= 0;
}
}
- bezt++;
}
+ /* recalculate handles */
calchandles_ipocurve(icu);
}
-
+/* 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)
{
- BezTriple *bezt;
- int a, ok= 1;
+ short ok= 1;
- while(ok) {
+ /* keep adjusting order of beztriples until nothing moves (bubble-sort) */
+ while (ok) {
ok= 0;
-
- if(icu->bezt) {
- bezt= icu->bezt;
- a= icu->totvert;
- while(a--) {
- if(a>0) {
- if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+
+ /* 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];
+ }
}
- if(bezt->vec[0][0]>bezt->vec[1][0] && bezt->vec[2][0]<bezt->vec[1][0]) {
- SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
- SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
- }
- else {
- 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];
- }
- bezt++;
}
}
- else {
-
- }
}
}
-int test_time_ipocurve(IpoCurve *icu)
+/* This function tests if any BezTriples are out of order, thus requiring a sort */
+int test_time_ipocurve (IpoCurve *icu)
{
- BezTriple *bezt;
int a;
- if(icu->bezt) {
- bezt= icu->bezt;
- a= icu->totvert-1;
- while(a--) {
- if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
- return 1;
- }
- bezt++;
- }
- }
- else {
+ /* currently, only need to test beztriples */
+ if (icu->bezt) {
+ BezTriple *bezt;
+ /* 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;
+ }
}
-
+
+ /* none need any swapping */
return 0;
}
-void correct_bezpart(float *v1, float *v2, float *v3, float *v4)
+/* --------- */
+
+/* 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)
{
- /* the total length of the handles is not allowed to be more
- * than the horizontal distance between (v1-v4)
- * this to prevent curve loops
- */
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(len1+len2==0.0) return;
- if(len1+len2 > len) {
+ /* if the handles have no length, no need to do any corrections */
+ if ((len1+len2) == 0.0)
+ 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]);
@@ -636,57 +801,86 @@ void correct_bezpart(float *v1, float *v2, float *v3, float *v4)
v3[0]= (v4[0]-fac*h2[0]);
v3[1]= (v4[1]-fac*h2[1]);
-
}
}
-/* *********************** ARITH *********************** */
+#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;
-int findzero(float x, float q0, float q1, float q2, float q3, float *o)
+ /* set interpolation mode for whole curve */
+ icu->ipo= ipo;
+
+ /* set interpolation mode of all beztriples */
+ for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++)
+ bezt->ipo= ipo;
+}
+#endif // TODO: enable when we have per-segment interpolation
+
+/* ***************************** Curve Calculations ********************************* */
+
+/* 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*(q1-q0);
- c2= 3*(q0-2*q1+q2);
- c3= q3-q0+3*(q1-q2);
+ c0= q0 - x;
+ c1= 3 * (q1 - q0);
+ c2= 3 * (q0 - 2*q1 + q2);
+ c3= q3 - q0 + 3 * (q1 - q2);
- if(c3!=0.0) {
+ 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) {
+
+ 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;
+ 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) {
+ else if (d == 0.0) {
t= Sqrt3d(-q);
- o[0]= (float)(2*t-a);
- if(o[0]>=SMALL && o[0]<=1.000001) nr++;
+ 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;
+
+ if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
else return nr;
}
else {
- phi= acos(-q/sqrt(-(p*p*p)));
+ 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;
+ 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;
}
}
@@ -695,83 +889,97 @@ int findzero(float x, float q0, float q1, float q2, float q3, float *o)
b=c1;
c=c0;
- if(a!=0.0) {
- p=b*b-4*a*c;
- if(p>0) {
+ 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[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;
+
+ 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 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) {
+ else if (b != 0.0) {
o[0]= (float)(-c/b);
- if(o[0]>=SMALL && o[0]<=1.000001) return 1;
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
else return 0;
}
- else if(c==0.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)
+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);
+ 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++) {
+ for (a=0; a < b; a++) {
t= o[a];
- o[a]= c0+t*c1+t*t*c2+t*t*t*c3;
+ o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
}
}
-void berekenx(float *f, float *o, int b)
+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++) {
+ 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;
+ o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
}
}
-/* we need the local transform = current transform - (parent transform + bone transform) */
-/* (local transform is on action channel level) */
-static void posechannel_get_local_transform(bPoseChannel *pchan, float *loc, float *eul, float *size)
+/* ***************************** 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)
+ */
+static void posechannel_get_local_transform (bPoseChannel *pchan, float loc[], float eul[], float size[])
{
- float diff_mat[4][4];
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) {
- /* get first the parent + bone transform in parmat */
-
/* bone transform itself */
Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
+
/* The bone's root offset (is in the parent's coordinate system) */
VECCOPY(offs_bone[3], pchan->bone->head);
+
/* Get the length translation of parent (length along y axis) */
offs_bone[3][1]+= pchan->parent->bone->length;
-
+
Mat4MulSerie(parmat, pchan->parent->pose_mat, offs_bone, NULL, NULL, NULL, NULL, NULL, NULL);
/* invert it */
@@ -780,64 +988,83 @@ static void posechannel_get_local_transform(bPoseChannel *pchan, float *loc, flo
else {
Mat4CpyMat3(offs_bone, pchan->bone->bone_mat);
VECCOPY(offs_bone[3], pchan->bone->head);
-
+
/* invert it */
Mat4Invert(imat, offs_bone);
-
}
/* difference: current transform - (parent transform + bone transform) */
Mat4MulMat4(diff_mat, pchan->pose_mat, imat);
- if(loc)
+ /* extract relevant components */
+ if (loc)
VECCOPY(loc, diff_mat[3]);
- if(eul)
+ if (eul)
Mat4ToEul(diff_mat, eul);
- if(size)
+ if (size)
Mat4ToSize(diff_mat, size);
-
}
-/* has to return a float value */
-static float eval_driver(IpoDriver *driver, float ipotime)
+/* 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
+ */
+static float eval_driver (IpoDriver *driver, float ipotime)
{
-
- if(driver->type == IPO_DRIVER_TYPE_PYTHON) {
+#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))
+ if ( (driver->name[0] == '\0') ||
+ (driver->flag & IPO_DRIVER_FLAG_INVALID) )
+ {
return 0.0f;
- /* this evals the expression and returns its result:
- * (on errors it reports, then returns 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);
}
- else {
- Object *ob= driver->ob;
+ else
+#endif /* DISABLE_PYTHON */
+ {
- if(ob==NULL) return 0.0f;
- if(ob->proxy_from)
+ 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;
- 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) {
+ /* 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;
}
- switch(driver->adrcode) {
+ /* 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:
- return ob->rot[0]/(M_PI_2/9.0);
- case OB_ROT_Y:
- return ob->rot[1]/(M_PI_2/9.0);
- case OB_ROT_Z:
- return ob->rot[2]/(M_PI_2/9.0);
+ 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:
@@ -846,14 +1073,20 @@ static float eval_driver(IpoDriver *driver, float ipotime)
return ob->size[2];
}
}
+
+ /* use given pose-channel as driver */
else { /* ID_AR */
bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name);
- 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... which is useful */
- if(driver->adrcode==OB_ROT_DIFF) {
+
+ /* 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) {
+
+ if (pchan2 && pchan2->bone) {
float q1[4], q2[4], quat[4], angle;
Mat4ToQuat(pchan->pose_mat, q1);
@@ -864,27 +1097,33 @@ static float eval_driver(IpoDriver *driver, float ipotime)
angle = 2.0f * (saacos(quat[0]));
angle= ABS(angle);
- return angle>M_PI?2.0f*M_PI-angle:angle;
+ return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle);
}
}
+
+ /* standard driver */
else {
float loc[3], eul[3], size[3];
+ /* 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);
-
- switch(driver->adrcode) {
+
+ 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:
- return eul[0]/(M_PI_2/9.0);
- case OB_ROT_Y:
- return eul[1]/(M_PI_2/9.0);
- case OB_ROT_Z:
- return eul[2]/(M_PI_2/9.0);
+ 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:
@@ -896,227 +1135,722 @@ static float eval_driver(IpoDriver *driver, float ipotime)
}
}
}
+
+ /* return 0.0f, as couldn't find relevant data to use */
return 0.0f;
}
-float eval_icu(IpoCurve *icu, float ipotime)
+/* evaluate and return the value of the given IPO-curve at the specified frame ("evaltime") */
+float eval_icu(IpoCurve *icu, float evaltime)
{
- BezTriple *bezt, *prevbezt;
- float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
- float cycdx, cycdy, ofs, cycyofs, cvalue = 0.0;
- int a, b;
+ float cvalue = 0.0f;
- cycyofs= 0.0;
-
- if(icu->driver) {
+ /* 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 */
- ipotime= cvalue= eval_driver(icu->driver, ipotime);
+ evaltime= cvalue= eval_driver(icu->driver, evaltime);
}
- if(icu->bezt) {
+
+ /* 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;
- a= icu->totvert-1;
+ lastbezt= prevbezt + a;
- /* cyclic? */
- if(icu->extrap & IPO_CYCL) {
- ofs= icu->bezt->vec[1][0];
- cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - ofs;
- cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
- if(cycdx!=0.0) {
-
- if(icu->extrap & IPO_DIR) {
- cycyofs= (float)floor((ipotime-ofs)/cycdx);
- cycyofs*= cycdy;
+ /* 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;
}
-
- ipotime= (float)(fmod(ipotime-ofs, cycdx)+ofs);
- if(ipotime<ofs) ipotime+= cycdx;
+
+ /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
+ evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
+ if (evaltime < ofs) evaltime += cycdx;
}
}
- /* endpoints? */
-
- if(prevbezt->vec[1][0]>=ipotime) {
- if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
- dx= prevbezt->vec[1][0]-ipotime;
- fac= prevbezt->vec[1][0]-prevbezt->vec[0][0];
- if(fac!=0.0) {
- fac= (prevbezt->vec[1][1]-prevbezt->vec[0][1])/fac;
- cvalue= prevbezt->vec[1][1]-fac*dx;
+ /* 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];
+
+ /* 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 cvalue= prevbezt->vec[1][1];
}
- else cvalue= prevbezt->vec[1][1];
-
- cvalue+= cycyofs;
+ else {
+ /* constant (IPO_HORIZ) extrapolation or constant interpolation,
+ * so just extend first keyframe's value
+ */
+ cvalue= prevbezt->vec[1][1];
+ }
}
- else if( (prevbezt+a)->vec[1][0]<=ipotime) {
- if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) {
- prevbezt+= a;
- dx= ipotime-prevbezt->vec[1][0];
- fac= prevbezt->vec[2][0]-prevbezt->vec[1][0];
-
- if(fac!=0) {
- fac= (prevbezt->vec[2][1]-prevbezt->vec[1][1])/fac;
- cvalue= prevbezt->vec[1][1]+fac*dx;
+ 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];
+
+ /* 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 cvalue= prevbezt->vec[1][1];
}
- else cvalue= (prevbezt+a)->vec[1][1];
-
- cvalue+= cycyofs;
+ else {
+ /* constant (IPO_HORIZ) extrapolation or constant interpolation,
+ * so just extend last keyframe's value
+ */
+ cvalue= lastbezt->vec[1][1];
+ }
}
else {
- while(a--) {
- if(prevbezt->vec[1][0]<=ipotime && bezt->vec[1][0]>=ipotime) {
- if(icu->ipo==IPO_CONST) {
- cvalue= prevbezt->vec[1][1]+cycyofs;
+ /* 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) {
- fac= bezt->vec[1][0]-prevbezt->vec[1][0];
- if(fac==0) cvalue= cycyofs+prevbezt->vec[1][1];
- else {
- fac= (ipotime-prevbezt->vec[1][0])/fac;
- cvalue= cycyofs+prevbezt->vec[1][1]+ fac*(bezt->vec[1][1]-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);
- b= findzero(ipotime, v1[0], v2[0], v3[0], v4[0], opl);
- if(b) {
+ /* 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]+cycyofs;
+ cvalue= opl[0];
break;
}
}
}
- prevbezt= bezt;
- bezt++;
}
}
+
+ /* apply y-offset (for 'cyclic extrapolation') to calculated value */
+ cvalue+= cycyofs;
}
-
- if(icu->ymin < icu->ymax) {
- if(cvalue < icu->ymin) cvalue= icu->ymin;
- else if(cvalue > icu->ymax) cvalue= icu->ymax;
+
+ /* 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;
}
-void calc_icu(IpoCurve *icu, float ctime)
+/* ------------------- 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);
}
-float calc_ipo_time(Ipo *ipo, float 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!
+ */
+void calc_ipo (Ipo *ipo, float ctime)
{
+ 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);
+ }
+ }
+}
- if(ipo && ipo->blocktype==ID_OB) {
- IpoCurve *icu= ipo->curve.first;
+/* ------------------- IPO-Block/Curve Calculation - Special Hacks ----------------------- */
- while(icu) {
- if (icu->adrcode==OB_TIME) {
- calc_icu(icu, ctime);
- return 10.0f*icu->curval;
- }
- icu= icu->next;
- }
+/* 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;
}
-void calc_ipo(Ipo *ipo, float 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);
+
+ /* 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);
+
+ /* value resulting from calculations is written into ctime! */
+ *ctime= icu->curval;
+ return 1;
+ }
+
+ /* 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;
- if(ipo==NULL) return;
- if(ipo->muteipo) return;
+ /* don't do anything without an IPO block */
+ if (ipo == NULL)
+ return;
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->driver || (icu->flag & IPO_LOCK)==0) {
- if((icu->flag & IPO_MUTE)==0)
- calc_icu(icu, ctime);
+ /* 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, getting a pointer to pchan var to write to
+ * - assume for now that only 'float' channels will ever get written into
+ */
+ 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);
}
}
}
-/* ************************************** */
-/* DO THE IPO! */
-/* ************************************** */
-void write_ipo_poin(void *poin, int type, float val)
+/* --------------------- 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);
+
+ /* calculate values, then flush to all users of this IPO block */
+ calc_ipo(ipo, ctime);
+ do_ipo_nocalc(ipo);
+ }
+}
+
+/* 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);
+}
- switch(type) {
- case IPO_FLOAT:
- *( (float *)poin)= val;
- break;
- case IPO_FLOAT_DEGR:
- *( (float *)poin)= (float)(val*M_PI_2/9.0);
- break;
- case IPO_INT:
- case IPO_INT_BIT:
- case IPO_LONG:
- *( (int *)poin)= (int)val;
- break;
- case IPO_SHORT:
- case IPO_SHORT_BIT:
- *( (short *)poin)= (short)val;
- break;
- case IPO_CHAR:
- case IPO_CHAR_BIT:
- *( (char *)poin)= (char)val;
- break;
+/* 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
+ */
+void do_ob_ipo (Object *ob)
+{
+ float ctime;
+ unsigned int lay;
+
+ if (ob->ipo == 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 */
+ }
}
}
-float read_ipo_poin(void *poin, int type)
+/* 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)
{
- float val = 0.0;
+ IpoCurve *icu;
+ void *poin;
+ int type;
- switch(type) {
- case IPO_FLOAT:
- val= *( (float *)poin);
+ for (icu= ipo->curve.first; icu; icu= icu->next) {
+ if (icu->driver) {
+ icu->curval= eval_icu(icu, ctime);
+
+ 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;
+ }
+
+ /* 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);
+ }
+ else
+ seq->facf1= seq->facf0= 1.0f;
+}
+
+/* --------- */
+
+
+/* exception: it does calc for objects...
+ * now find out why this routine was used anyway!
+ */
+void do_ipo_nocalc (Ipo *ipo)
+{
+ Object *ob;
+ Material *ma;
+ Tex *tex;
+ World *wo;
+ Lamp *la;
+ Camera *ca;
+ bSound *snd;
+
+ if (ipo == NULL)
+ return;
+
+ /* 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 IPO_FLOAT_DEGR:
- val= *( (float *)poin);
- val = (float)(val/(M_PI_2/9.0));
+ 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 IPO_INT:
- case IPO_INT_BIT:
- case IPO_LONG:
- val= (float)(*( (int *)poin));
+ 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 IPO_SHORT:
- case IPO_SHORT_BIT:
- val= *( (short *)poin);
+ 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 IPO_CHAR:
- case IPO_CHAR_BIT:
- val= *( (char *)poin);
+ 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;
}
- return val;
}
-static void *give_tex_poin(Tex *tex, int adrcode, int *type )
+/* 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;
+ }
+ }
+
+ /* 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;
+ }
+ }
+ }
+
+ /* 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);
+ }
+ }
+
+ /* 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);
+ }
+
+ /* 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);
+ }
+ }
+ }
+}
+
+
+/* --------------------- Assorted ----------------------------- */
+
+/* clear delta-transforms on all Objects which use the given IPO block */
+void clear_delta_obipo(Ipo *ipo)
+{
+ Object *ob;
+
+ /* only search if there's an IPO */
+ if (ipo == NULL)
+ 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);
+ }
+ }
+ }
+}
+
+/* ***************************** IPO - DataAPI ********************************* */
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!!
+
+/* These functions here should be replaced eventually by the Data API, as this is
+ * inflexible duplication...
+ */
+
+/* --------------------- Get Pointer API ----------------------------- */
+
+/* get pointer to pose-channel's channel, but set appropriate flags first */
+void *get_pchan_ipo_poin (bPoseChannel *pchan, int adrcode)
+{
+ 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;
+ }
+
+ /* return pointer */
+ return poin;
+}
+
+/* get texture channel */
+static void *give_tex_poin (Tex *tex, int adrcode, int *type )
{
- void *poin=0;
+ void *poin= NULL;
- switch(adrcode) {
+ switch (adrcode) {
case TE_NSIZE:
poin= &(tex->noisesize); break;
case TE_TURB:
@@ -1169,17 +1903,18 @@ static void *give_tex_poin(Tex *tex, int adrcode, int *type )
poin= &(tex->bright); break;
case TE_CONTRA:
poin= &(tex->contrast); break;
-
}
+ /* return pointer */
return poin;
}
-void *give_mtex_poin(MTex *mtex, int adrcode )
+/* get texture-slot/mapping channel */
+void *give_mtex_poin (MTex *mtex, int adrcode)
{
- void *poin=0;
-
- switch(adrcode) {
+ void *poin= NULL;
+
+ switch (adrcode) {
case MAP_OFS_X:
poin= &(mtex->ofs[0]); break;
case MAP_OFS_Y:
@@ -1210,6 +1945,7 @@ void *give_mtex_poin(MTex *mtex, int adrcode )
poin= &(mtex->dispfac); break;
}
+ /* return pointer */
return poin;
}
@@ -1226,1284 +1962,923 @@ void *give_mtex_poin(MTex *mtex, int adrcode )
/* from misc_util: flip the bytes from x */
/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
+
+/* general function to get pointer to source/destination data */
+void *get_ipo_poin (ID *id, IpoCurve *icu, int *type)
{
void *poin= NULL;
- Object *ob;
- Material *ma;
- MTex *mtex;
- Tex *tex;
- Lamp *la;
- Sequence *seq;
- World *wo;
- ParticleSettings *part;
+ MTex *mtex= NULL;
+ /* most channels will have float data, but those with other types will override this */
*type= IPO_FLOAT;
- if( GS(id->name)==ID_OB) {
-
- 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;
+ /* data is divided into 'blocktypes' based on ID-codes */
+ switch (GS(id->name)) {
+ case ID_OB: /* object channels ----------------------------- */
+ {
+ Object *ob= (Object *)id;
- 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;
+ 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_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;
- }
- }
- else if( GS(id->name)==ID_MA) {
-
- 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;
- 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;
- }
-
- if(poin==NULL) {
- mtex= 0;
- 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];
+ 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;
- if(mtex) {
- poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
- }
- }
- }
- else if( GS(id->name)==ID_TE) {
- tex= (Tex *)id;
-
- if(tex) poin= give_tex_poin(tex, icu->adrcode, type);
- }
- else if( GS(id->name)==ID_SEQ) {
- seq= (Sequence *)id;
-
- switch(icu->adrcode) {
- case SEQ_FAC1:
- poin= &(seq->facf0); break;
- }
- }
- else if( GS(id->name)==ID_CU) {
-
- poin= &(icu->curval);
-
- }
- else if( GS(id->name)==ID_KE) {
- KeyBlock *kb= ((Key *)id)->block.first;
-
- for(; kb; kb= kb->next)
- if(kb->adrcode==icu->adrcode)
+ 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;
- if(kb)
- poin= &(kb->curval);
-
- }
- else if(GS(id->name)==ID_WO) {
-
- 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) {
- mtex= 0;
- 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];
-
- if(mtex) {
- poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
- }
- }
- }
- else if( GS(id->name)==ID_LA) {
-
- 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;
- }
-
- if(poin==NULL) {
- mtex= 0;
- 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];
-
- if(mtex) {
- poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) );
}
}
- }
- else if(GS(id->name)==ID_CA) {
- Camera *ca= (Camera *)id;
-
- /* yafray: aperture & focal distance params */
- 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;
- case CAM_SHIFT_X:
- poin= &(ca->shiftx); break;
- case CAM_SHIFT_Y:
- poin= &(ca->shifty); break;
- }
- }
- else if(GS(id->name)==ID_SO) {
- 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;
- }
- }
- else if( GS(id->name)==ID_PA) {
-
- 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;
- }
- }
-
- return poin;
-}
-
-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;
-
- if(icu->blocktype==ID_OB) {
-
- if(icu->adrcode==OB_LAY) {
- icu->ipo= IPO_CONST;
- icu->vartype= IPO_BITS;
- }
-
- }
- else if(icu->blocktype==ID_MA) {
-
- 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 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:
- icu->ymax= 2.0; break;
+ 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:
- icu->ipo= IPO_CONST;
- icu->vartype= IPO_BITS; break;
- case MA_RAYM:
- icu->ymax= 1.0; break;
+ poin= &(ma->mode); *type= IPO_INT_BIT; break; // evil... dumping bitflags directly to user!
+ case MA_HASIZE:
+ poin= &(ma->hasize); break;
case MA_TRANSLU:
- icu->ymax= 1.0; break;
- case MA_IOR:
- icu->ymin= 1.0;
- icu->ymax= 3.0; break;
+ poin= &(ma->translucency); break;
+ case MA_RAYM:
+ poin= &(ma->ray_mirror); break;
case MA_FRESMIR:
- icu->ymax= 5.0; break;
+ poin= &(ma->fresnel_mir); break;
case MA_FRESMIRI:
- icu->ymin= 1.0;
- icu->ymax= 5.0; break;
+ poin= &(ma->fresnel_mir_i); break;
case MA_FRESTRA:
- icu->ymax= 5.0; break;
+ poin= &(ma->fresnel_tra); break;
case MA_FRESTRAI:
- icu->ymin= 1.0;
- icu->ymax= 5.0; break;
+ poin= &(ma->fresnel_tra_i); break;
case MA_ADD:
- icu->ymax= 1.0; break;
- default:
- icu->ymax= 1.0; break;
+ poin= &(ma->add); break;
+ }
+
+ 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];
+
+ if (mtex)
+ poin= give_mtex_poin(mtex, (icu->adrcode & (MA_MAP1-1)));
}
}
- 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 ID_TE: /* texture channels ----------------------------- */
+ {
+ Tex *tex= (Tex *)id;
- 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;
+ 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;
}
}
- }
- else if(icu->blocktype==ID_TE) {
- switch(icu->adrcode & (MA_MAP1-1)) {
- case TE_NSIZE:
- icu->ymin= 0.0001;
- icu->ymax= 2.0; break;
- case TE_NDEPTH:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0; break;
- case TE_NTYPE:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 1.0; break;
- case TE_TURB:
- icu->ymax= 200.0; break;
- case TE_VNW1:
- case TE_VNW2:
- case TE_VNW3:
- case TE_VNW4:
- icu->ymax= 2.0;
- icu->ymin= -2.0; break;
- case TE_VNMEXP:
- icu->ymax= 10.0;
- icu->ymin= 0.01; break;
- case TE_VN_DISTM:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0; break;
- case TE_VN_COLT:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 3.0; break;
- case TE_ISCA:
- icu->ymax= 10.0;
- icu->ymin= 0.01; break;
- case TE_DISTA:
- icu->ymax= 10.0; break;
- case TE_MG_TYP:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 6.0; break;
- case TE_MGH:
- icu->ymin= 0.0001;
- icu->ymax= 2.0; break;
- case TE_MG_LAC:
- case TE_MG_OFF:
- case TE_MG_GAIN:
- icu->ymax= 6.0; break;
- case TE_MG_OCT:
- icu->ymax= 8.0; break;
- case TE_N_BAS1:
- case TE_N_BAS2:
- icu->vartype= IPO_SHORT;
- icu->ipo= IPO_CONST;
- icu->ymax= 8.0; break;
- case TE_COL_R:
- icu->ymax= 0.0; break;
- case TE_COL_G:
- icu->ymax= 2.0; break;
- case TE_COL_B:
- icu->ymax= 2.0; break;
- case TE_BRIGHT:
- icu->ymax= 2.0; break;
- case TE_CONTRA:
- icu->ymax= 5.0; break;
-
+ break;
+ case ID_CU: /* curve channels ----------------------------- */
+ {
+ poin= &(icu->curval);
}
- }
- else if(icu->blocktype==ID_SEQ) {
-
- icu->ymax= 1.0;
-
- }
- else if(icu->blocktype==ID_CU) {
-
- icu->ymax= 1.0;
-
- }
- else if(icu->blocktype==ID_WO) {
-
- if(icu->adrcode < MA_MAP1) {
- switch(icu->adrcode) {
+ break;
+ case ID_KE: /* shapekey channels ----------------------------- */
+ {
+ Key *key= (Key *)id;
+ KeyBlock *kb;
+
+ for(kb= key->block.first; kb; kb= kb->next) {
+ if (kb->adrcode == icu->adrcode)
+ break;
+ }
+
+ 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:
- icu->ymax= 5.0; break;
+ 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:
- break;
-
- default:
- icu->ymax= 1.0;
- break;
+ poin= &(wo->starsize); 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.0;
- icu->ymin= -100.0;
- 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.0;
+ 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];
+
+ if (mtex)
+ poin= give_mtex_poin(mtex, (icu->adrcode & (MA_MAP1-1)));
}
}
- }
- else if(icu->blocktype==ID_LA) {
- if(icu->adrcode < MA_MAP1) {
- switch(icu->adrcode) {
+ break;
+ case ID_LA: /* lamp channels ----------------------------- */
+ {
+ Lamp *la= (Lamp *)id;
+
+ switch (icu->adrcode) {
case LA_ENERGY:
- case LA_DIST:
- break;
-
+ 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:
- icu->ymax= 1.0; break;
- case LA_SPOTSI:
- icu->ymax= 180.0; break;
+ poin= &(la->att2); break;
case LA_HALOINT:
- icu->ymax= 5.0; break;
+ poin= &(la->haint); break;
+ }
+
+ 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)));
}
}
- 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.0;
- icu->ymin= -100.0;
+ 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 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.0;
+ 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;
+
+ case CAM_SHIFT_X:
+ poin= &(ca->shiftx); break;
+ case CAM_SHIFT_Y:
+ poin= &(ca->shifty); break;
}
}
- }
- else if(icu->blocktype==ID_CA) {
-
- /* yafray: aperture & focal distance params */
- switch(icu->adrcode) {
- case CAM_LENS:
- icu->ymin= 1.0;
- icu->ymax= 1000.0;
- break;
- case CAM_STA:
- icu->ymin= 0.001f;
- break;
- case CAM_END:
- icu->ymin= 0.1f;
- break;
- case CAM_YF_APERT:
- icu->ymin = 0.0;
- icu->ymax = 2.0;
- break;
- case CAM_YF_FDIST:
- icu->ymin = 0.0;
- icu->ymax = 5000.0;
break;
+ case ID_SO: /* sound channels ----------------------------- */
+ {
+ bSound *snd= (bSound *)id;
- case CAM_SHIFT_X:
- case CAM_SHIFT_Y:
- icu->ymin= -2.0f;
- icu->ymax= 2.0f;
- break;
+ 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;
+ }
}
- }
- else if(icu->blocktype==ID_SO) {
-
- switch(icu->adrcode) {
- case SND_VOLUME:
- icu->ymin= 0.0;
- icu->ymax= 1.0;
- break;
- case SND_PITCH:
- icu->ymin= -12.0;
- icu->ymin= 12.0;
- break;
- case SND_PANNING:
- icu->ymin= 0.0;
- icu->ymax= 1.0;
- break;
- case SND_ATTEN:
- icu->ymin= 0.0;
- icu->ymin= 1.0;
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;
+
+ 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;
+ }
}
- }
- else if(icu->blocktype==ID_PA){
-
- 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.0;
- break;
- case PART_CLUMP:
- icu->ymin= -1.0;
- icu->ymax= 1.0;
break;
- case PART_DRAG:
- case PART_DAMP:
- case PART_LENGTH:
- icu->ymin= 0.0;
- icu->ymax= 1.0;
- break;
- case PART_KINK_SHAPE:
- icu->ymin= -0.999;
- icu->ymax= 0.999;
- break;
- }
}
- else if(icu->blocktype==ID_CO) {
- icu->ymin= 0.0;
- icu->ymax= 1.0f;
- }
-
- /* by default, slider limits will be icu->ymin and icu->ymax */
- icu->slide_min= icu->ymin;
- icu->slide_max= icu->ymax;
-}
-/* not for actions or constraints! */
-void execute_ipo(ID *id, Ipo *ipo)
-{
- IpoCurve *icu;
- void *poin;
- int type;
-
- if(ipo==NULL) return;
-
- 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);
- }
+ /* return pointer */
+ return poin;
}
-void *get_pchan_ipo_poin(bPoseChannel *pchan, int adrcode)
+/* --------------------- IPO-Curve Limits ----------------------------- */
+
+/* set limits for IPO-curve
+ * Note: must be synced with UI and PyAPI
+ */
+void set_icu_vars (IpoCurve *icu)
{
- void *poin= NULL;
+ /* defaults. 0.0 for y-extents makes these ignored */
+ icu->ymin= icu->ymax= 0.0;
+ icu->ipo= IPO_BEZ;
- switch (adrcode) {
- case AC_QUAT_W:
- poin= &(pchan->quat[0]);
- pchan->flag |= POSE_ROT;
+ switch (icu->blocktype) {
+ case ID_OB: /* object channels ----------------------------- */
+ {
+ if (icu->adrcode == OB_LAY) {
+ icu->ipo= IPO_CONST;
+ icu->vartype= IPO_BITS;
+ }
+ }
break;
- case AC_QUAT_X:
- poin= &(pchan->quat[1]);
- pchan->flag |= POSE_ROT;
+ 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 AC_QUAT_Y:
- poin= &(pchan->quat[2]);
- pchan->flag |= POSE_ROT;
+ 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 AC_QUAT_Z:
- poin= &(pchan->quat[3]);
- pchan->flag |= POSE_ROT;
+ case ID_SEQ: /* sequence channels ----------------------------- */
+ {
+ icu->ymax= 1.0f;
+ }
break;
- case AC_LOC_X:
- poin= &(pchan->loc[0]);
- pchan->flag |= POSE_LOC;
+ case ID_CU: /* curve channels ----------------------------- */
+ {
+ icu->ymax= 1.0f;
+ }
break;
- case AC_LOC_Y:
- poin= &(pchan->loc[1]);
- pchan->flag |= POSE_LOC;
+ 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 AC_LOC_Z:
- poin= &(pchan->loc[2]);
- pchan->flag |= POSE_LOC;
- break;
- case AC_SIZE_X:
- poin= &(pchan->size[0]);
- pchan->flag |= POSE_SIZE;
+ 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 AC_SIZE_Y:
- poin= &(pchan->size[1]);
- pchan->flag |= POSE_SIZE;
+ 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;
+ }
+ }
break;
- case AC_SIZE_Z:
- poin= &(pchan->size[2]);
- pchan->flag |= POSE_SIZE;
+ 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;
+ }
+ }
break;
- }
- return poin;
-}
-
-void execute_action_ipo(bActionChannel *achan, bPoseChannel *pchan)
-{
-
- if(achan && achan->ipo) {
- IpoCurve *icu;
- 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);
- //printf("execute_action_ipo wrote_ipo_poin: %f\n", icu->curval);
- //printf("%s has poin %p value %f\n", achan->name, poin, icu->curval);
+ 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;
}
}
+ break;
+ case ID_CO: /* constraint channels ----------------------------- */
+ {
+ icu->ymin= 0.0f;
+ icu->ymax= 1.0f;
+ }
+ break;
}
+
+ /* by default, slider limits will be icu->ymin and icu->ymax */
+ icu->slide_min= icu->ymin;
+ icu->slide_max= icu->ymax;
}
-/* exception: it does calc for objects...
- * now find out why this routine was used anyway!
- */
-void do_ipo_nocalc(Ipo *ipo)
+/* --------------------- Pointer I/O API ----------------------------- */
+
+/* write the given value directly into the given pointer */
+void write_ipo_poin (void *poin, int type, float val)
{
- Object *ob;
- Material *ma;
- Tex *tex;
- World *wo;
- Lamp *la;
- Camera *ca;
- bSound *snd;
-
- if(ipo==NULL) return;
-
- switch(ipo->blocktype) {
- case ID_OB:
- ob= G.main->object.first;
- while(ob) {
- if(ob->ipo==ipo) {
- do_ob_ipo(ob);
- /* execute_ipo((ID *)ob, ipo); */
- }
- ob= ob->id.next;
- }
- break;
- case ID_MA:
- ma= G.main->mat.first;
- while(ma) {
- if(ma->ipo==ipo) execute_ipo((ID *)ma, ipo);
- ma= ma->id.next;
- }
- break;
- case ID_TE:
- tex= G.main->tex.first;
- while(tex) {
- if(tex->ipo==ipo) execute_ipo((ID *)tex, ipo);
- tex=tex->id.next;
- }
+ /* 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 ID_WO:
- wo= G.main->world.first;
- while(wo) {
- if(wo->ipo==ipo) execute_ipo((ID *)wo, ipo);
- wo= wo->id.next;
- }
+
+ 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 ID_LA:
- la= G.main->lamp.first;
- while(la) {
- if(la->ipo==ipo) execute_ipo((ID *)la, ipo);
- la= la->id.next;
- }
+
+ case IPO_INT:
+ case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil!
+ case IPO_LONG:
+ *((int *)poin)= (int)val;
break;
- case ID_CA:
- ca= G.main->camera.first;
- while(ca) {
- if(ca->ipo==ipo) execute_ipo((ID *)ca, ipo);
- ca= ca->id.next;
- }
+
+ case IPO_SHORT:
+ case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil!
+ *((short *)poin)= (short)val;
break;
- case ID_SO:
- snd= G.main->sound.first;
- while(snd) {
- if(snd->ipo==ipo) execute_ipo((ID *)snd, ipo);
- snd= snd->id.next;
- }
+
+ case IPO_CHAR:
+ case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil!
+ *((char *)poin)= (char)val;
break;
}
}
-void do_ipo(Ipo *ipo)
-{
- if(ipo) {
- float ctime= frame_to_float(G.scene->r.cfra);
- calc_ipo(ipo, ctime);
-
- do_ipo_nocalc(ipo);
- }
-}
-
-
-
-void do_mat_ipo(Material *ma)
-{
- float ctime;
-
- if(ma==NULL || ma->ipo==NULL) return;
-
- ctime= frame_to_float(G.scene->r.cfra);
- /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */
-
- calc_ipo(ma->ipo, ctime);
-
- execute_ipo((ID *)ma, ma->ipo);
-}
-
-void do_ob_ipo(Object *ob)
-{
- float ctime;
- unsigned int lay;
-
- if(ob->ipo==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);
-
- calc_ipo(ob->ipo, ctime);
-
- /* Patch: remember localview */
- lay= ob->lay & 0xFF000000;
-
- execute_ipo((ID *)ob, ob->ipo);
-
- 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 */
- }
- }
-}
-
-void do_ob_ipodrivers(Object *ob, Ipo *ipo, float ctime)
+/* read the value from the pointer that was obtained */
+float read_ipo_poin (void *poin, int type)
{
- IpoCurve *icu;
- void *poin;
- int type;
-
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->driver) {
- icu->curval= eval_icu(icu, ctime);
- poin= get_ipo_poin((ID *)ob, icu, &type);
- if(poin) write_ipo_poin(poin, type, icu->curval);
- }
- }
-}
-
-void do_seq_ipo(Sequence *seq, int cfra)
-{
- float ctime, div;
-
- /* seq_ipo has an exception: calc both fields immediately */
+ float val = 0.0;
- 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;
- }
+ /* 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)
+ */
+ switch (type) {
+ case IPO_FLOAT:
+ val= *((float *)poin);
+ break;
- /* 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);
-
- }
- else seq->facf1= seq->facf0= 1.0f;
-}
-
-int has_ipo_code(Ipo *ipo, int code)
-{
- IpoCurve *icu;
-
- if(ipo==NULL) return 0;
-
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->adrcode==code) return 1;
- }
- return 0;
-}
-
-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) {
- /* only update layer when an ipo */
- if( has_ipo_code(base->object->ipo, OB_LAY) ) {
- do_ob_ipo(base->object);
- base->lay= base->object->lay;
- }
- }
-
- /* layers for the set...*/
- if(G.scene->set) {
- for(base= G.scene->set->base.first; base; base= base->next) {
- if( has_ipo_code(base->object->ipo, OB_LAY) ) {
- do_ob_ipo(base->object);
- base->lay= base->object->lay;
- }
- }
- }
-
-
- ipo= G.main->ipo.first;
- while(ipo) {
- if(ipo->id.us && ipo->blocktype!=ID_OB) {
- calc_ipo(ipo, ctime);
- }
- ipo= ipo->id.next;
- }
-
- for(tex= G.main->tex.first; tex; tex= tex->id.next) {
- if(tex->ipo) execute_ipo((ID *)tex, tex->ipo);
- }
-
- for(ma= G.main->mat.first; ma; ma= ma->id.next) {
- if(ma->ipo) execute_ipo((ID *)ma, ma->ipo);
- }
-
- for(wo= G.main->world.first; wo; wo= wo->id.next) {
- if(wo->ipo) execute_ipo((ID *)wo, wo->ipo);
- }
-
- for(key= G.main->key.first; key; key= key->id.next) {
- if(key->ipo) execute_ipo((ID *)key, key->ipo);
- }
-
- la= G.main->lamp.first;
- while(la) {
- if(la->ipo) execute_ipo((ID *)la, la->ipo);
- la= la->id.next;
- }
-
- ca= G.main->camera.first;
- while(ca) {
- if(ca->ipo) execute_ipo((ID *)ca, ca->ipo);
- ca= ca->id.next;
- }
-
- snd= G.main->sound.first;
- while(snd) {
- if(snd->ipo) execute_ipo((ID *)snd, snd->ipo);
- snd= snd->id.next;
- }
-
- /* process FAC Ipos used as volume envelopes */
- ed= G.scene->ed;
- if (ed) {
- seq= ed->seqbasep->first;
- while(seq) {
- if ((seq->type == SEQ_RAM_SOUND
- || seq->type == SEQ_HD_SOUND) && (seq->ipo) &&
- (seq->startdisp<=G.scene->r.cfra+2) &&
- (seq->enddisp>G.scene->r.cfra))
- do_seq_ipo(seq, G.scene->r.cfra);
- seq= seq->next;
- }
- }
-
-}
-
-
-int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime)
-{
- IpoCurve *icu;
-
- if(ipo==NULL) return 0;
-
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->adrcode == adrcode) {
- if(icu->flag & IPO_LOCK);
- else calc_icu(icu, *ctime);
-
- *ctime= icu->curval;
- return 1;
- }
- }
-
- return 0;
-}
-
-
-/* ************************** */
-
-void clear_delta_obipo(Ipo *ipo)
-{
- Object *ob;
+ 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;
- if(ipo==NULL) return;
+ 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;
- ob= G.main->object.first;
- while(ob) {
- if(ob->id.lib==NULL) {
- if(ob->ipo==ipo) {
- memset(&ob->dloc, 0, 12);
- memset(&ob->drot, 0, 12);
- memset(&ob->dsize, 0, 12);
- }
- }
- ob= ob->id.next;
+ case IPO_CHAR:
+ case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil
+ val= *((char *)poin);
+ break;
}
-}
-
-void add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
-{
- CfraElem *ce, *cen;
-
- ce= lb->first;
- while(ce) {
-
- if( ce->cfra==bezt->vec[1][0] ) {
- /* do because of double keys */
- if(bezt->f2 & SELECT) ce->sel= bezt->f2;
- return;
- }
- else if(ce->cfra > bezt->vec[1][0]) break;
-
- ce= ce->next;
- }
- 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 value */
+ return val;
}
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!!
-void make_cfra_list(Ipo *ipo, ListBase *elems)
-{
- IpoCurve *icu;
- BezTriple *bezt;
- int a;
-
- if(ipo->blocktype==ID_OB) {
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->flag & IPO_VISIBLE) {
- switch(icu->adrcode) {
- case OB_DLOC_X:
- case OB_DLOC_Y:
- case OB_DLOC_Z:
- case OB_DROT_X:
- case OB_DROT_Y:
- case OB_DROT_Z:
- case OB_DSIZE_X:
- case OB_DSIZE_Y:
- case OB_DSIZE_Z:
-
- case OB_LOC_X:
- case OB_LOC_Y:
- case OB_LOC_Z:
- case OB_ROT_X:
- case OB_ROT_Y:
- case OB_ROT_Z:
- case OB_SIZE_X:
- case OB_SIZE_Y:
- case OB_SIZE_Z:
- case OB_PD_FSTR:
- case OB_PD_FFALL:
- case OB_PD_SDAMP:
- case OB_PD_RDAMP:
- case OB_PD_PERM:
- case OB_PD_FMAXD:
- bezt= icu->bezt;
- if(bezt) {
- a= icu->totvert;
- while(a--) {
- add_to_cfra_elem(elems, bezt);
- bezt++;
- }
- }
- break;
- }
- }
- }
- }
- else if(ipo->blocktype==ID_AC) {
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->flag & IPO_VISIBLE) {
- switch(icu->adrcode) {
- case AC_LOC_X:
- case AC_LOC_Y:
- case AC_LOC_Z:
- case AC_SIZE_X:
- case AC_SIZE_Y:
- case AC_SIZE_Z:
- case AC_QUAT_W:
- case AC_QUAT_X:
- case AC_QUAT_Y:
- case AC_QUAT_Z:
- bezt= icu->bezt;
- if(bezt) {
- a= icu->totvert;
- while(a--) {
- add_to_cfra_elem(elems, bezt);
- bezt++;
- }
- }
- break;
- }
- }
- }
- }
- else {
- for(icu= ipo->curve.first; icu; icu= icu->next) {
- if(icu->flag & IPO_VISIBLE) {
- bezt= icu->bezt;
- if(bezt) {
- a= icu->totvert;
- while(a--) {
- add_to_cfra_elem(elems, bezt);
- bezt++;
- }
- }
- }
- }
- }
-
- /* what's the point of this little block of code? */
-#if 0
- if(ipo->showkey==0) {
- /* deselect all keys */
- ce= elems->first;
- while(ce) {
- ce->sel= 0;
- ce= ce->next;
- }
- }
-#endif
-}
-
-/* *********************** INTERFACE FOR KETSJI ********** */
-
+/* ***************************** IPO <--> GameEngine Interface ********************************* */
-int IPO_GetChannels(Ipo *ipo, IPO_Channel *channels)
+/* channels is max 32 items, allocated by calling function */
+short IPO_GetChannels (Ipo *ipo, IPO_Channel *channels)
{
- /* channels is max 32 items, allocated by calling function */
-
IpoCurve *icu;
- int total=0;
+ int total = 0;
- if(ipo==NULL) return 0;
+ /* don't do anything with no IPO-block */
+ if (ipo == NULL)
+ return 0;
- for(icu= ipo->curve.first; icu; icu= icu->next) {
+ /* 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;
- total++;
- if(total>31) break;
- }
+ /* return the number of channels stored */
return total;
}
-
-
/* Get the float value for channel 'channel' at time 'ctime' */
-
-float IPO_GetFloatValue(Ipo *ipo, IPO_Channel channel, float ctime)
+float IPO_GetFloatValue (Ipo *ipo, IPO_Channel channel, float ctime)
{
- if(ipo==NULL) return 0;
+ /* don't evaluate if no IPO to use */
+ if (ipo == NULL)
+ return 0;
+ /* only calculate the specified channel */
calc_ipo_spec(ipo, channel, &ctime);
- if (OB_ROT_X <= channel && channel <= OB_DROT_Z) {
+ /* 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;
}