diff options
-rw-r--r-- | source/blender/blenkernel/BKE_ipo.h | 121 | ||||
-rw-r--r-- | source/blender/blenkernel/SConscript | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim_sys.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/blender.c | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/depsgraph.c | 149 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/ipo.c | 2837 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/key.c | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 72 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 32 | ||||
-rw-r--r-- | source/blender/blenloader/SConscript | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 28 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_draw.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit.c | 33 | ||||
-rwxr-xr-x | source/blender/makesrna/intern/rna_pose.c | 2 |
15 files changed, 739 insertions, 2576 deletions
diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h index fae62b4a23e..a3f451438bd 100644 --- a/source/blender/blenkernel/BKE_ipo.h +++ b/source/blender/blenkernel/BKE_ipo.h @@ -24,7 +24,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): 2008, Joshua Leung (Animation Cleanup) + * Contributor(s): 2008,2009 Joshua Leung (Animation Cleanup, Animation Systme Recode) * * ***** END GPL LICENSE BLOCK ***** */ @@ -35,127 +35,18 @@ extern "C" { #endif - -/* -------- IPO-Curve (Bezier) Calculations ---------- */ - -// xxx perhaps this should be in curve api not in anim api -void correct_bezpart(float *v1, float *v2, float *v3, float *v4); - - -// XXX this file will soon be depreceated... -#if 0 // XXX old animation system - -typedef struct CfraElem { - struct CfraElem *next, *prev; - float cfra; - int sel; -} CfraElem; - +struct Main; struct Ipo; -struct IpoCurve; -struct MTex; -struct Material; -struct Scene; -struct Object; -struct Sequence; -struct ListBase; -struct BezTriple; -struct ID; -struct bPoseChannel; -struct bActionChannel; -struct rctf; -/* ------------ Time Management ------------ */ +void do_versions_ipo_to_animato(struct Main *main); -float frame_to_float(struct Scene *scene, int cfra); +/* --------------------- xxx stuff ------------------------ */ -/* ------------ IPO Management ---------- */ - -void free_ipo_curve(struct IpoCurve *icu); void free_ipo(struct Ipo *ipo); -void ipo_default_v2d_cur(struct Scene *scene, int blocktype, struct rctf *cur); - -struct Ipo *add_ipo(struct Scene *scene, char *name, int idcode); -struct Ipo *copy_ipo(struct Ipo *ipo); - -void ipo_idnew(struct Ipo *ipo); - -struct IpoCurve *find_ipocurve(struct Ipo *ipo, int adrcode); -short has_ipo_code(struct Ipo *ipo, int code); - -/* -------------- Make Local -------------- */ - -void make_local_obipo(struct Ipo *ipo); -void make_local_matipo(struct Ipo *ipo); -void make_local_keyipo(struct Ipo *ipo); -void make_local_ipo(struct Ipo *ipo); - -/* ------------ IPO-Curve Sanity ---------------- */ - -void calchandles_ipocurve(struct IpoCurve *icu); -void testhandles_ipocurve(struct IpoCurve *icu); -void sort_time_ipocurve(struct IpoCurve *icu); -int test_time_ipocurve(struct IpoCurve *icu); - -void set_interpolation_ipocurve(struct IpoCurve *icu, short ipo); - -/* -------- IPO-Curve (Bezier) Calculations ---------- */ - +// xxx perhaps this should be in curve api not in anim api void correct_bezpart(float *v1, float *v2, float *v3, float *v4); -int findzero(float x, float q0, float q1, float q2, float q3, float *o); -void berekeny(float f1, float f2, float f3, float f4, float *o, int b); -void berekenx(float *f, float *o, int b); - -/* -------- IPO Curve Calculation and Evaluation --------- */ - -float eval_icu(struct IpoCurve *icu, float ipotime); -void calc_icu(struct IpoCurve *icu, float ctime); -float calc_ipo_time(struct Ipo *ipo, float ctime); -void calc_ipo(struct Ipo *ipo, float ctime); - -void calc_ipo_range(struct Ipo *ipo, float *start, float *end); - -/* ------------ Keyframe Column Tools -------------- */ - -void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt); -void make_cfra_list(struct Ipo *ipo, struct ListBase *elems); - -/* ---------------- IPO DataAPI ----------------- */ - -void write_ipo_poin(void *poin, int type, float val); -float read_ipo_poin(void *poin, int type); - -void *give_mtex_poin(struct MTex *mtex, int adrcode ); -void *get_pchan_ipo_poin(struct bPoseChannel *pchan, int adrcode); -void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type); - -void set_icu_vars(struct IpoCurve *icu); - -/* ---------------- IPO Execution --------------- */ - -void execute_ipo(struct ID *id, struct Ipo *ipo); -void execute_action_ipo(struct bActionChannel *achan, struct bPoseChannel *pchan); - -void do_ipo_nocalc(struct Scene *scene, struct Ipo *ipo); -void do_ipo(struct Scene *scene, struct Ipo *ipo); -void do_mat_ipo(struct Scene *scene, struct Material *ma); -void do_ob_ipo(struct Scene *scene, struct Object *ob); -void do_seq_ipo(struct Scene *scene, struct Sequence *seq, int cfra); -void do_ob_ipodrivers(struct Object *ob, struct Ipo *ipo, float ctime); - -void do_all_data_ipos(struct Scene *scene); -short calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime); -void clear_delta_obipo(struct Ipo *ipo); - -/* ----------- IPO <-> GameEngine API ---------------- */ - -/* the short is an IPO_Channel... */ - -short IPO_GetChannels(struct Ipo *ipo, short *channels); -float IPO_GetFloatValue(struct Ipo *ipo, short c, float ctime); - -#endif // XXX old animation system + #ifdef __cplusplus }; diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index aae4addd71e..bf09b2aac03 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -52,4 +52,4 @@ if env['BF_NO_ELBEEM']: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [155] ) +env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = Split(defs), libtype=['core'], priority = [165] ) diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fb2a9731a40..30e5daeeb3b 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -86,7 +86,10 @@ AnimData *BKE_id_add_animdata (ID *id) if (id_has_animdata(id)) { IdAdtTemplate *iat= (IdAdtTemplate *)id; - iat->adt= MEM_callocN(sizeof(AnimData), "AnimData"); + /* check if there's already AnimData, in which case, don't add */ + if (iat->adt == NULL) + iat->adt= MEM_callocN(sizeof(AnimData), "AnimData"); + return iat->adt; } else @@ -232,7 +235,8 @@ static void animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve * free_path= animsys_remap_path(remap, fcu->rna_path, &path); /* write value to setting */ - animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval); + if (path) + animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval); /* free temp path-info */ if (free_path) @@ -586,7 +590,7 @@ void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short re * or be layered on top of existing animation data. * - Drivers should be in the appropriate order to be evaluated without problems... */ - if ((recalc & ADT_RECALC_DRIVERS) && (adt->recalc & ADT_RECALC_DRIVERS)) + if ((recalc & ADT_RECALC_DRIVERS) /*&& (adt->recalc & ADT_RECALC_DRIVERS)*/) // XXX for now, don't check yet, as depsgraph hasn't been updated { animsys_evaluate_drivers(&id_ptr, adt, ctime); } @@ -615,7 +619,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) { ID *id; - //printf("Evaluate all animation - %f \n", ctime); + printf("Evaluate all animation - %f \n", ctime); /* macro for less typing */ #define EVAL_ANIM_IDS(first) \ @@ -640,7 +644,7 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->camera.first); /* shapekeys */ - // TODO... + EVAL_ANIM_IDS(main->key.first); /* curves */ // TODO... diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index ae18a75daa0..2ad0c98bb79 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -74,6 +74,7 @@ #include "BKE_font.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_ipo.h" #include "BKE_main.h" #include "BKE_node.h" #include "BKE_object.h" @@ -371,12 +372,12 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename) //setscreen(G.curscreen); } + // XXX is this in the right place? + do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching + /* baseflags, groups, make depsgraph, etc */ set_scene_bg(CTX_data_scene(C)); - /* clear BONE_UNKEYED flags, these are not valid anymore for proxies */ - framechange_poses_clear_unkeyed(); - /* last stage of do_versions actually, that sets recalc flags for recalc poses */ for(ob= G.main->object.first; ob; ob= ob->id.next) { if(ob->type==OB_ARMATURE) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 57dca4ddcb5..983a9bc9ac6 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -303,50 +303,66 @@ DagForest * dag_init() return forest; } -static void dag_add_driver_relation(Ipo *ipo, DagForest *dag, DagNode *node, int isdata) +/* isdata = object data... */ +// XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... +static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata) { - IpoCurve *icu; + FCurve *fcu; DagNode *node1; - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->driver) { - - if (icu->driver->type == IPO_DRIVER_TYPE_PYTHON) { - - if ((icu->driver->flag & IPO_DRIVER_FLAG_INVALID) || (icu->driver->name[0] == '\0')) - continue; /* empty or invalid expression */ + for (fcu= adt->drivers.first; fcu; fcu= fcu->next) { + ChannelDriver *driver= fcu->driver; + + if (driver->type == DRIVER_TYPE_PYTHON) { + /* PyDriver / 'Expression' */ + + /* skip if invalid in some way */ + if ((driver->flag & DRIVER_FLAG_INVALID) || (driver->expression[0] == '\0')) + continue; #ifndef DISABLE_PYTHON - else { - /* now we need refs to all objects mentioned in this - * pydriver expression, to call 'dag_add_relation' - * for each of them */ - Object **obarray = BPY_pydriver_get_objects(icu->driver); - if (obarray) { - Object *ob, **oba = obarray; - - while (*oba) { - ob = *oba; - node1 = dag_get_node(dag, ob); - if (ob->type == OB_ARMATURE) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Python Ipo Driver"); - else - dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Python Ipo Driver"); - oba++; - } - - MEM_freeN(obarray); + else { + /* now we need refs to all objects mentioned in this + * pydriver expression, to call 'dag_add_relation' + * for each of them */ + Object **obarray = BPY_pydriver_get_objects(fcu->driver); + if (obarray) { + Object *ob, **oba = obarray; + + while (*oba) { + ob = *oba; + node1 = dag_get_node(dag, ob); + if (ob->type == OB_ARMATURE) + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Python Driver"); + else + dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Python Driver"); + oba++; } + + MEM_freeN(obarray); } -#endif /* DISABLE_PYTHON */ - } - else if (icu->driver->ob) { - node1 = dag_get_node(dag, icu->driver->ob); - if(icu->driver->blocktype==ID_AR) - dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Ipo Driver"); - else - dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver"); } +#endif /* DISABLE_PYTHON */ + } + else if (driver->type == DRIVER_TYPE_ROTDIFF) { + // XXX rotational difference + } + else { + /* normal channel-drives-channel */ + node1 = dag_get_node(dag, driver->id); // XXX we assume that id is an object... + + // XXX what happens for bone drivers? + dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver"); } +#if 0 // XXX old 'normal' type + + else if (icu->driver->ob) { + node1 = dag_get_node(dag, icu->driver->ob); + if(icu->driver->blocktype==ID_AR) + dag_add_relation(dag, node1, node, isdata?DAG_RL_DATA_DATA:DAG_RL_DATA_OB, "Ipo Driver"); + else + dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver"); + } +#endif // XXX old 'normal' type } } @@ -371,7 +387,6 @@ static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Objec static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, Object *ob, int mask) { bConstraint *con; - bConstraintChannel *conchan; DagNode * node; DagNode * node2; DagNode * node3; @@ -426,6 +441,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } /* driver dependencies, nla modifiers */ +#if 0 // XXX old animation system if(ob->ipo) dag_add_driver_relation(ob->ipo, dag, node, 0); @@ -466,6 +482,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } +#endif // XXX old animation system + if (ob->adt) + dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation + + key= ob_get_key(ob); + if (key && key->adt) + dag_add_driver_relation(key->adt, dag, node, 1); + if (ob->modifiers.first) { ModifierData *md; @@ -515,11 +539,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA|DAG_RL_OB_OB, "Proxy"); /* inverted relation, so addtoroot shouldn't be set to zero */ } + + if (ob->type==OB_CAMERA) { Camera *cam = (Camera *)ob->data; - if (cam->ipo) { - dag_add_driver_relation(cam->ipo, dag, node, 1); - } + if (cam->adt) + dag_add_driver_relation(cam->adt, dag, node, 1); if (cam->dof_ob) { node2 = dag_get_node(dag, cam->dof_ob); dag_add_relation(dag,node2,node,DAG_RL_OB_OB, "Camera DoF"); @@ -527,10 +552,10 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } if (ob->type==OB_LAMP) { Lamp *la = (Lamp *)ob->data; - if (la->ipo) { - dag_add_driver_relation(la->ipo, dag, node, 1); - } + if (la->adt) + dag_add_driver_relation(la->adt, dag, node, 1); } + if (ob->transflag & OB_DUPLI) { if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { GroupObject *go; @@ -566,9 +591,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O node2 = dag_get_node(dag, cu->taperobj); dag_add_relation(dag,node2,node,DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Curve Taper"); } - if(cu->ipo) - dag_add_driver_relation(cu->ipo, dag, node, 1); - + if (cu->adt) + dag_add_driver_relation(cu->adt, dag, node, 1); } else if(ob->type==OB_FONT) { Curve *cu= ob->data; @@ -1953,24 +1977,6 @@ static int object_modifiers_use_time(Object *ob) return 0; } -#if 0 // XXX old animation system -static int exists_channel(Object *ob, char *name) -{ - bActionStrip *strip; - - if(ob->action) - if(get_action_channel(ob->action, name)) - return 1; - - for (strip=ob->nlastrips.first; strip; strip=strip->next) - if(get_action_channel(strip->act, name)) - return 1; - - return 0; -} -#endif // XXX old animation system - - static short animdata_use_time(AnimData *adt) { NlaTrack *nlt; @@ -2023,14 +2029,8 @@ static void dag_object_time_update_flags(Object *ob) } #if 0 // XXX old animation system - if(ob->action || ob->nlastrips.first) { - /* since actions now are mixed, we set the recalcs on the safe side */ - ob->recalc |= OB_RECALC_OB; - if(ob->type==OB_ARMATURE) - ob->recalc |= OB_RECALC_DATA; - else if(exists_channel(ob, "Shape")) - ob->recalc |= OB_RECALC_DATA; - else if(ob->dup_group) { + if(ob->nlastrips.first) { + if(ob->dup_group) { bActionStrip *strip; /* this case is for groups with nla, whilst nla target has no action or nla */ for(strip= ob->nlastrips.first; strip; strip= strip->next) { @@ -2041,6 +2041,7 @@ static void dag_object_time_update_flags(Object *ob) } #endif // XXX old animation system if(animdata_use_time(ob->adt)) ob->recalc |= OB_RECALC; + if((ob->adt) && (ob->type==OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA; if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; @@ -2316,6 +2317,7 @@ void DAG_pose_sort(Object *ob) ListBase targets = {NULL, NULL}; bConstraintTarget *ct; +#if 0 // XXX old animation system... driver stuff to watch out for if(con->ipo) { IpoCurve *icu; for(icu= con->ipo->curve.first; icu; icu= icu->next) { @@ -2327,7 +2329,7 @@ void DAG_pose_sort(Object *ob) if(target) { node2 = dag_get_node(dag, target); dag_add_relation(dag, node2, node, 0, "Ipo Driver"); - + /* uncommented this line, results in dependencies * not being added properly for this constraint, * what is the purpose of this? - brecht */ @@ -2336,6 +2338,7 @@ void DAG_pose_sort(Object *ob) } } } +#endif // XXX old animation system... driver stuff to watch out for if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index f547b483092..e4c4e7a37b4 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1190,7 +1190,7 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo cycles= data->after_cycles; } } - if ELEM3(0, side, mode, cycles) + if ELEM(0, side, mode) return; /* extrapolation mode is 'cyclic' - find relative place within a cycle */ @@ -1209,7 +1209,12 @@ static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, flo if (cycdx == 0) return; /* check that cyclic is still enabled for the specified time */ - if ( ((float)side * (evaltime - ofs) / cycdx) > cycles ) + if (cycles == 0) { + /* catch this case so that we don't exit when we have cycles=0 + * as this indicates infinite cycles... + */ + } + else if ( ((float)side * (evaltime - ofs) / cycdx) > cycles ) return; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 16d173bf5d6..0c9897f9b30 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -23,13 +23,19 @@ * * The Original Code is: all of this file. * - * Contributor(s): 2008, Joshua Leung (IPO System cleanup) + * Contributor(s): 2008,2009 Joshua Leung (IPO System cleanup, Animation System Recode) * * ***** END GPL LICENSE BLOCK ***** */ -#if 0 // XXX old animation system - +/* NOTE: + * + * This file is no longer used to provide tools for the depreceated IPO system. Instead, it + * is only used to house the conversion code to the new system. + * + * -- Joshua Leung, Jan 2009 + */ + #include <math.h> #include <stdio.h> #include <string.h> @@ -40,8 +46,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" +#include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_camera_types.h" #include "DNA_lamp_types.h" @@ -61,13 +69,16 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_dynstr.h" #include "BKE_utildefines.h" +#include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_blender.h" #include "BKE_curve.h" #include "BKE_constraint.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_library.h" @@ -75,1744 +86,732 @@ #include "BKE_mesh.h" #include "BKE_object.h" -#ifndef DISABLE_PYTHON -#include "BPY_extern.h" /* for BPY_pydriver_eval() */ -#endif - -#define SMALL -1.0e-10 - -/* ***************************** Adrcode Blocktype Defines ********************************* */ - -/* This array concept was meant to make sure that defines such as OB_LOC_X - don't have to be enumerated, also for backward compatibility, future changes, - and to enable it all can be accessed with a for-next loop. - - This should whole adrcode system should eventually be replaced by a proper Data API -*/ - - -int co_ar[CO_TOTIPO]= { - CO_ENFORCE, CO_HEADTAIL -}; - -int ob_ar[OB_TOTIPO]= { - OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z, - OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z, - OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z, - OB_LAY, OB_TIME, OB_COL_R, OB_COL_G, OB_COL_B, OB_COL_A, - OB_PD_FSTR, OB_PD_FFALL, OB_PD_SDAMP, OB_PD_RDAMP, OB_PD_PERM, OB_PD_FMAXD -}; - -int ac_ar[AC_TOTIPO]= { - AC_LOC_X, AC_LOC_Y, AC_LOC_Z, - AC_EUL_X, AC_EUL_Y, AC_EUL_Z, - AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z, - AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z -}; - -int ma_ar[MA_TOTIPO]= { - MA_COL_R, MA_COL_G, MA_COL_B, - MA_SPEC_R, MA_SPEC_G, MA_SPEC_B, - MA_MIR_R, MA_MIR_G, MA_MIR_B, - MA_REF, MA_ALPHA, MA_EMIT, MA_AMB, - MA_SPEC, MA_HARD, MA_SPTR, MA_IOR, - MA_MODE, MA_HASIZE, MA_TRANSLU, MA_RAYM, - MA_FRESMIR, MA_FRESMIRI, MA_FRESTRA, MA_FRESTRAI, MA_ADD, - - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF, MA_MAP1+MAP_DISP -}; - -int te_ar[TE_TOTIPO] ={ - - TE_NSIZE, TE_NDEPTH, TE_NTYPE, TE_TURB, - - TE_VNW1, TE_VNW2, TE_VNW3, TE_VNW4, - TE_VNMEXP, TE_VN_COLT, TE_VN_DISTM, - - TE_ISCA, TE_DISTA, - - TE_MG_TYP, TE_MGH, TE_MG_LAC, TE_MG_OCT, TE_MG_OFF, TE_MG_GAIN, - - TE_N_BAS1, TE_N_BAS2, - - TE_COL_R, TE_COL_G, TE_COL_B, TE_BRIGHT, TE_CONTRA -}; - -int seq_ar[SEQ_TOTIPO]= { - SEQ_FAC1 -}; -int cu_ar[CU_TOTIPO]= { - CU_SPEED -}; -int wo_ar[WO_TOTIPO]= { - WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B, - WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI, - WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE, +/* *************************************************** */ +/* Old-Data Freeing Tools */ - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF -}; - -int la_ar[LA_TOTIPO]= { - LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B, - LA_DIST, LA_SPOTSI, LA_SPOTBL, - LA_QUAD1, LA_QUAD2, LA_HALOINT, - - MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, - MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, - MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, - MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF -}; - -/* yafray: aperture & focal distance curves added */ -/* qdn: FDIST now available to Blender as well for defocus node */ -int cam_ar[CAM_TOTIPO]= { - CAM_LENS, CAM_STA, CAM_END, CAM_YF_APERT, CAM_YF_FDIST, CAM_SHIFT_X, CAM_SHIFT_Y -}; - -int snd_ar[SND_TOTIPO]= { - SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN -}; - -int fluidsim_ar[FLUIDSIM_TOTIPO]= { - FLUIDSIM_VISC, FLUIDSIM_TIME, - FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z , - FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z , - FLUIDSIM_ACTIVE, - FLUIDSIM_ATTR_FORCE_STR, FLUIDSIM_ATTR_FORCE_RADIUS, - FLUIDSIM_VEL_FORCE_STR, FLUIDSIM_VEL_FORCE_RADIUS, -}; - -int part_ar[PART_TOTIPO]= { - PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE, - PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP, - PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE, - PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD -}; - -/* ************************** Data-Level Functions ************************* */ - -/* ---------------------- Freeing --------------------------- */ - -/* frees the ipo curve itself too */ -void free_ipo_curve (IpoCurve *icu) -{ - if (icu == NULL) - return; - - if (icu->bezt) - MEM_freeN(icu->bezt); - if (icu->driver) - MEM_freeN(icu->driver); - - MEM_freeN(icu); -} - -/* do not free ipo itself */ +/* Free data from old IPO-Blocks (those which haven't been converted), but not IPO block itself */ +// XXX this shouldn't be necessary anymore, but may occur while not all data is converted yet void free_ipo (Ipo *ipo) { IpoCurve *icu, *icn; - - if (ipo == NULL) - return; + int n= 0; for (icu= ipo->curve.first; icu; icu= icn) { icn= icu->next; + n++; - /* 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 */ -// XXX users usually find these zoom settings problematic... -void ipo_default_v2d_cur (Scene *scene, int blocktype, rctf *cur) -{ - switch (blocktype) { - case ID_CA: - cur->xmin= (float)scene->r.sfra; - cur->xmax= (float)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)(scene->r.sfra - 0.1f); - cur->xmax= (float)scene->r.efra; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+1.1f; - break; + if (icu->bezt) MEM_freeN(icu->bezt); + if (icu->bp) MEM_freeN(icu->bp); + if (icu->driver) MEM_freeN(icu->driver); - case ID_TE: - cur->xmin= (float)(scene->r.sfra - 0.1f); - cur->xmax= (float)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)(scene->r.sfra - 0.1f); - cur->xmax= (float)scene->r.efra; - cur->ymin= (float)-0.1f; - cur->ymax= (float)+2.1f; - break; - - default: /* ID_OB and everything else */ - cur->xmin= (float)scene->r.sfra; - cur->xmax= (float)scene->r.efra; - cur->ymin= -5.0f; - cur->ymax= +5.0f; - break; + BLI_freelinkN(&ipo->curve, icu); } -} - -/* create a new IPO block (allocates the block) */ -Ipo *add_ipo (Scene *scene, char name[], int blocktype) -{ - Ipo *ipo; - ipo= alloc_libblock(&G.main->ipo, ID_IP, name); - ipo->blocktype= blocktype; - if(scene) ipo_default_v2d_cur(scene, blocktype, &ipo->cur); - - return ipo; + printf("Freed %d (Unconverted) Ipo-Curves from IPO '%s' \n", n, ipo->id.name+2); } -/* ---------------------- Copy --------------------------- */ +/* *************************************************** */ +/* ADRCODE to RNA-Path Conversion Code */ -/* duplicate an IPO block and all its data */ -Ipo *copy_ipo (Ipo *src) +/* Object types */ +static char *ob_adrcodes_to_paths (int adrcode, int *array_index) { - Ipo *dst; - IpoCurve *icu; - - if (src == NULL) - return NULL; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - dst= copy_libblock(src); - BLI_duplicatelist(&dst->curve, &src->curve); - - for (icu= src->curve.first; icu; icu= icu->next) { - icu->bezt= MEM_dupallocN(icu->bezt); + /* result depends on adrcode */ + switch (adrcode) { + case OB_LOC_X: + *array_index= 0; return "location"; + case OB_LOC_Y: + *array_index= 1; return "location"; + case OB_LOC_Z: + *array_index= 2; return "location"; + case OB_DLOC_X: + *array_index= 0; return "delta_location"; + case OB_DLOC_Y: + *array_index= 1; return "delta_location"; + case OB_DLOC_Z: + *array_index= 2; return "delta_location"; - if (icu->driver) - icu->driver= MEM_dupallocN(icu->driver); + case OB_ROT_X: + *array_index= 0; return "rotation"; + case OB_ROT_Y: + *array_index= 1; return "rotation"; + case OB_ROT_Z: + *array_index= 2; return "rotation"; + case OB_DROT_X: + *array_index= 0; return "delta_rotation"; + case OB_DROT_Y: + *array_index= 1; return "delta_rotation"; + case OB_DROT_Z: + *array_index= 2; return "delta_rotation"; + + case OB_SIZE_X: + *array_index= 0; return "scale"; + case OB_SIZE_Y: + *array_index= 1; return "scale"; + case OB_SIZE_Z: + *array_index= 2; return "scale"; + case OB_DSIZE_X: + *array_index= 0; return "delta_scale"; + case OB_DSIZE_Y: + *array_index= 1; return "delta_scale"; + case OB_DSIZE_Z: + *array_index= 2; return "delta_scale"; + +#if 0 + case OB_LAY: // XXX EVIL BITFLAG ALERT! this one will need special attention... + // poin= &(ob->lay); *type= IPO_INT_BIT; break; + return NULL; + + case OB_COL_R: + poin= &(ob->col[0]); break; + case OB_COL_G: + poin= &(ob->col[1]); break; + case OB_COL_B: + poin= &(ob->col[2]); break; + case OB_COL_A: + poin= &(ob->col[3]); break; + + case OB_PD_FSTR: + if (ob->pd) poin= &(ob->pd->f_strength); + break; + case OB_PD_FFALL: + if (ob->pd) poin= &(ob->pd->f_power); + break; + case OB_PD_SDAMP: + if (ob->pd) poin= &(ob->pd->pdef_damp); + break; + case OB_PD_RDAMP: + if (ob->pd) poin= &(ob->pd->pdef_rdamp); + break; + case OB_PD_PERM: + if (ob->pd) poin= &(ob->pd->pdef_perm); + break; + case OB_PD_FMAXD: + if (ob->pd) poin= &(ob->pd->maxdist); + break; +#endif } - return dst; -} - -/* ---------------------- 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) { - IpoCurve *icu; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->driver) - ID_NEW(icu->driver->ob); - } - } -} - -/* --------------------- Find + Check ----------------------- */ - -/* find the IPO-curve within a given IPO-block with the adrcode of interest */ -IpoCurve *find_ipocurve (Ipo *ipo, int adrcode) -{ - 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 +/* PoseChannel types + * NOTE: pchan name comes from 'actname' added earlier... */ -void make_local_obipo (Ipo *src) +static char *pchan_adrcodes_to_paths (int adrcode, int *array_index) { - Object *ob; - Ipo *dst; - int local=0, lib=0; + /* set array index like this in-case nothing sets it correctly */ + *array_index= 0; - /* check if only local and/or lib */ - for (ob= G.main->object.first; ob; ob= ob->id.next) { - if (ob->ipo == src) { - if (ob->id.lib) lib= 1; - else local= 1; - } - } - - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; + /* result depends on adrcode */ + switch (adrcode) { + case AC_QUAT_W: + *array_index= 0; return "rotation"; + case AC_QUAT_X: + *array_index= 1; return "rotation"; + case AC_QUAT_Y: + *array_index= 2; return "rotation"; + case AC_QUAT_Z: + *array_index= 3; return "rotation"; + +#if 0 // XXX these were not 'official' channels (i.e. not in bf-releases)... these will need separate wrapping to work... + case AC_EUL_X: + *array_index= 0; return "rotation"; + case AC_EUL_Y: + *array_index= 1; return "rotation"; + case AC_EUL_Z: + *array_index= 2; return "rotation"; +#endif + case -1: // XXX special case for rotation drivers... until eulers are added... + *array_index= 0; return "rotation"; + + case AC_LOC_X: + *array_index= 0; return "location"; + case AC_LOC_Y: + *array_index= 1; return "location"; + case AC_LOC_Z: + *array_index= 2; return "location"; - for (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--; - } - } - } - } -} - -/* 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 *dst; - int local=0, lib=0; - - /* check if only local and/or lib */ - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == src) { - if (ma->id.lib) lib= 1; - else local= 1; - } + case AC_SIZE_X: + *array_index= 0; return "scale"; + case AC_SIZE_Y: + *array_index= 1; return "scale"; + case AC_SIZE_Z: + *array_index= 2; return "scale"; } - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; - - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == src) { - if (ma->id.lib == NULL) { - ma->ipo= dst; - dst->id.us++; - src->id.us--; - } - } - } - } + /* for debugging only */ + printf("ERROR: unmatched PoseChannel setting (code %d) \n", adrcode); + return NULL; } -/* make the given IPO local (for ShapeKeys) - * - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy +/* ShapeKey types + * NOTE: as we don't have access to the keyblock where the data comes from (for now), + * we'll just use numerical indicies for now... */ -void make_local_keyipo (Ipo *src) +static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index) { - Key *key; - Ipo *dst; - int local=0, lib=0; - - /* check if only local and/or lib */ - for (key= G.main->key.first; key; key= key->id.next) { - if (key->ipo == src) { - if (key->id.lib) lib= 1; - else local= 1; - } - } + static char buf[128]; - /* only local - set flag */ - if (local && lib==0) { - src->id.lib= 0; - src->id.flag= LIB_LOCAL; - new_id(0, (ID *)src, 0); - } - /* mixed: make copy */ - else if (local && lib) { - dst= copy_ipo(src); - dst->id.us= 0; - - for (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--; - } - } - } - } + /* block will be attached to ID_KE block, and setting that we alter is the 'value' (which sets keyblock.curval) */ + // XXX adrcode 0 was dummy 'speed' curve + sprintf(buf, "keys[%d].value", adrcode-1); // XXX this doesn't seem too safe... + return buf; } +/* ------- */ -/* generic call to make IPO's local */ -void make_local_ipo (Ipo *ipo) +/* Allocate memory for RNA-path for some property given a blocktype, adrcode, and 'root' parts of path + * Input: + * - blocktype, adrcode - determines setting to get + * - actname, constname - used to build path + * Output: + * - array_index - index in property's array (if applicable) to use + * - return - the allocated path... + */ +char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index) { - /* 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; - } + DynStr *path= BLI_dynstr_new(); + char *propname=NULL, *rpath=NULL; + char buf[512]; + int dummy_index= 0; - /* when more than 1 user, can only make local for certain blocktypes */ - switch (ipo->blocktype) { - case ID_OB: - make_local_obipo(ipo); + /* get property name based on blocktype */ + switch (blocktype) { + case ID_OB: /* object */ + propname= ob_adrcodes_to_paths(adrcode, &dummy_index); break; - case ID_MA: - make_local_matipo(ipo); + + case ID_PO: /* pose channel */ + propname= pchan_adrcodes_to_paths(adrcode, &dummy_index); break; - case ID_KE: - make_local_keyipo(ipo); + + case ID_KE: /* shapekeys */ + propname= shapekey_adrcodes_to_paths(adrcode, &dummy_index); break; - } -} - -/* ***************************** Keyframe Column Tools ********************************* */ - -/* add a BezTriple to a column */ -void add_to_cfra_elem(ListBase *lb, BezTriple *bezt) -{ - CfraElem *ce, *cen; - - for (ce= lb->first; ce; ce= ce->next) { - /* double key? */ - if (ce->cfra == bezt->vec[1][0]) { - if (bezt->f2 & SELECT) ce->sel= bezt->f2; - return; - } - /* should key be inserted before this column? */ - else if (ce->cfra > bezt->vec[1][0]) break; - } - - /* create a new column */ - cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); - if (ce) BLI_insertlinkbefore(lb, ce, cen); - else BLI_addtail(lb, cen); - - cen->cfra= bezt->vec[1][0]; - cen->sel= bezt->f2; -} - -/* make a list of keyframe 'columns' in an IPO block */ -void make_cfra_list (Ipo *ipo, ListBase *elems) -{ - 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); - } - } - } + /* XXX problematic blocktypes */ + case ID_CU: + propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var... + break; + + case ID_SEQ: + //SEQ_FAC1: + // poin= &(seq->facf0); // XXX this doesn't seem to be included anywhere in sequencer RNA... + break; + + /* special hacks */ + case -1: + /* special case for rotdiff drivers... we don't need a property for this... */ + break; + + // TODO... add other blocktypes... + default: + printf("IPO2ANIMATO WARNING: No path for blocktype %d, adrcode %d yet \n", blocktype, adrcode); + break; } -} - -/* ***************************** Timing Stuff ********************************* */ - -/* This (evil) function is needed to cope with two legacy Blender rendering features - * mblur (motion blur that renders 'subframes' and blurs them together), and fields - * rendering. Thus, the use of ugly globals from object.c - */ -// BAD... EVIL... JUJU...!!!! -float frame_to_float (Scene *scene, int cfra) /* see also bsystem_time in object.c */ -{ - extern float bluroffs; /* bad stuff borrowed from object.c */ - extern float fieldoffs; - float ctime; - ctime= (float)cfra; - ctime+= bluroffs+fieldoffs; - ctime*= scene->r.framelen; - - return ctime; -} - -/* Calculate the extents of IPO block's keyframes */ -void calc_ipo_range (Ipo *ipo, float *start, float *end) -{ - IpoCurve *icu; - float min=999999999.0f, max=-999999999.0f; - short foundvert=0; - - if (ipo) { - for (icu=ipo->curve.first; icu; icu=icu->next) { - if (icu->totvert) { - min= MIN2(min, icu->bezt[0].vec[1][0]); - max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]); - foundvert=1; - } - } - } - - /* minimum length is 1 frame */ - if (foundvert) { - if (min == max) max += 1.0f; - *start= min; - *end= max; - } - else { - *start= 0.0f; - *end= 1.0f; - } -} - -/* ***************************** IPO Curve Sanity ********************************* */ -/* The functions here are used in various parts of Blender, usually after some editing - * of keyframe data has occurred. They ensure that keyframe data is properly ordered and - * that the handles are correctly - */ - -/* This function recalculates the handles of an IPO-Curve - * If the BezTriples have been rearranged, sort them first before using this. - */ -void calchandles_ipocurve (IpoCurve *icu) -{ - BezTriple *bezt, *prev, *next; - int a= icu->totvert; - - /* Error checking: - * - need at least two points - * - need bezier keys - * - only bezier-interpolation has handles (for now) + /* check if any property found + * - blocktype < 0 is special case for a specific type of driver, where we don't need a property name... */ - if (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 */ - - /* for automatic ease in and out */ - if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) { - /* only do this on first or last beztriple */ - if ((a==0) || (a==icu->totvert-1)) { - /* set both handles to have same horizontal value as keyframe */ - if (icu->extrap==IPO_HORIZ) { - bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; - } - } - } + if ((propname == NULL) && (blocktype > 0)) { + /* nothing was found, so exit */ + if (array_index) + *array_index= 0; + + BLI_dynstr_free(path); - /* advance pointers for next iteration */ - prev= bezt; - if (a == 1) next= NULL; - else next++; - bezt++; + return NULL; } -} - -/* Use when IPO-Curve with handles has changed - * It treats all BezTriples with the following rules: - * - PHASE 1: do types have to be altered? - * -> Auto handles: become aligned when selection status is NOT(000 || 111) - * -> Vector handles: become 'nothing' when (one half selected AND other not) - * - PHASE 2: recalculate handles -*/ -void testhandles_ipocurve (IpoCurve *icu) -{ - BezTriple *bezt; - int a; - - /* only beztriples have handles (bpoints don't though) */ - if (ELEM(NULL, icu, icu->bezt)) - return; - - /* loop over beztriples */ - for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) { - short flag= 0; - - /* flag is initialised as selection status - * of beztriple control-points (labelled 0,1,2) - */ - if (bezt->f1 & SELECT) flag |= (1<<0); // == 1 - if (bezt->f2 & SELECT) flag |= (1<<1); // == 2 - if (bezt->f3 & SELECT) flag |= (1<<2); // == 4 - - /* one or two handles selected only */ - if (ELEM(flag, 0, 7)==0) { - /* auto handles become aligned */ - if (bezt->h1==HD_AUTO) - bezt->h1= HD_ALIGN; - if(bezt->h2==HD_AUTO) - bezt->h2= HD_ALIGN; - - /* vector handles become 'free' when only one half selected */ - if(bezt->h1==HD_VECT) { - /* only left half (1 or 2 or 1+2) */ - if (flag < 4) - bezt->h1= 0; - } - if(bezt->h2==HD_VECT) { - /* only right half (4 or 2+4) */ - if (flag > 3) - bezt->h2= 0; - } - } + else { + if (array_index) + *array_index= dummy_index; } - - /* 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) -{ - short ok= 1; - /* keep adjusting order of beztriples until nothing moves (bubble-sort) */ - while (ok) { - ok= 0; - - /* currently, will only be needed when there are beztriples */ - if (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]; - } - } - } - } + /* append preceeding bits to path */ + if ((actname && actname[0]) && (constname && constname[0])) { + /* Constraint in Pose-Channel */ + sprintf(buf, "pose.pose_channels[\"%s\"].constraints[\"%s\"]", actname, constname); } -} - -/* This function tests if any BezTriples are out of order, thus requiring a sort */ -int test_time_ipocurve (IpoCurve *icu) -{ - int a; - - /* 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; - } + else if (actname && actname[0]) { + /* Pose-Channel */ + sprintf(buf, "pose.pose_channels[\"%s\"]", actname); } - - /* none need any swapping */ - return 0; -} - -/* --------- */ - -/* The total length of the handles is not allowed to be more - * than the horizontal distance between (v1-v4). - * This is to prevent curve loops. -*/ -void correct_bezpart (float *v1, float *v2, float *v3, float *v4) -{ - float h1[2], h2[2], len1, len2, len, fac; - - /* calculate handle deltas */ - h1[0]= v1[0]-v2[0]; - h1[1]= v1[1]-v2[1]; - h2[0]= v4[0]-v3[0]; - h2[1]= v4[1]-v3[1]; - - /* calculate distances: - * - len = span of time between keyframes - * - len1 = length of handle of start key - * - len2 = length of handle of end key - */ - len= v4[0]- v1[0]; - len1= (float)fabs(h1[0]); - len2= (float)fabs(h2[0]); - - /* if the handles have no length, no need to do any corrections */ - if ((len1+len2) == 0.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]); - v2[1]= (v1[1]-fac*h1[1]); + else if (constname && constname[0]) { + /* Constraint in Object */ + sprintf(buf, "constraints[\"%s\"]", constname); + } + else + strcpy(buf, ""); /* empty string */ + BLI_dynstr_append(path, buf); + + /* append property to path (only if applicable) */ + if (blocktype > 0) { + /* need to add dot before property if there was anything precceding this */ + if (buf[0]) + BLI_dynstr_append(path, "."); - v3[0]= (v4[0]-fac*h2[0]); - v3[1]= (v4[1]-fac*h2[1]); + /* now write name of property */ + BLI_dynstr_append(path, propname); } -} - -/* 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. - */ -// XXX move to readfile.c for patching old files only.. -void set_interpolation_ipocurve (IpoCurve *icu, short ipo) -{ - BezTriple *bezt; - int a; - /* validate arguments */ - if (icu == NULL) return; - if (ELEM3(ipo, IPO_CONST, IPO_LIN, IPO_BEZ)==0) return; - - /* set interpolation mode for whole curve */ - icu->ipo= ipo; + /* convert to normal MEM_malloc'd string */ + rpath= BLI_dynstr_get_cstring(path); + BLI_dynstr_free(path); - /* set interpolation mode of all beztriples */ - for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++) - bezt->ipo= ipo; + /* return path... */ + return rpath; } -/* ***************************** Curve Calculations ********************************* */ +/* *************************************************** */ +/* Conversion Utilities */ -/* find root/zero */ -int findzero (float x, float q0, float q1, float q2, float q3, float *o) +/* Convert IpoDriver to ChannelDriver - will free the old data (i.e. the old driver) */ +static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver) { - double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; - int nr= 0; - - c0= q0 - x; - c1= 3 * (q1 - q0); - c2= 3 * (q0 - 2*q1 + q2); - c3= q3 - q0 + 3 * (q1 - q2); + ChannelDriver *cdriver; - if (c3 != 0.0) { - a= c2/c3; - b= c1/c3; - c= c0/c3; - a= a/3; - - p= b/3 - a*a; - q= (2*a*a*a - a*b + c) / 2; - d= q*q + p*p*p; - - if (d > 0.0) { - t= sqrt(d); - o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; - } - else if (d == 0.0) { - t= Sqrt3d(-q); - o[0]= (float)(2*t - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)(-t-a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; - } - else { - phi= acos(-q / sqrt(-(p*p*p))); - t= sqrt(-p); - p= cos(phi/3); - q= sqrt(3 - 3*p*p); - o[0]= (float)(2*t*p - a); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)(-t * (p + q) - a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++; - o[nr]= (float)(-t * (p - q) - a); - - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; - } + /* allocate memory for new driver */ + cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + + /* if 'pydriver', just copy data across */ + if (idriver->type == IPO_DRIVER_TYPE_PYTHON) { + /* PyDriver only requires the expression to be copied */ + cdriver->type = DRIVER_TYPE_PYTHON; + strcpy(cdriver->expression, idriver->name); // XXX is this safe? } else { - a=c2; - b=c1; - c=c0; - - if (a != 0.0) { - // discriminant - p= b*b - 4*a*c; - - if (p > 0) { - p= sqrt(p); - o[0]= (float)((-b-p) / (2 * a)); + /* what to store depends on the 'blocktype' (ID_OB or ID_PO - object or posechannel) */ + if (idriver->blocktype == ID_AR) { + /* ID_PO */ + if (idriver->adrcode == OB_ROT_DIFF) { + /* Rotational Difference is a special type of driver now... */ + cdriver->type= DRIVER_TYPE_ROTDIFF; - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++; - o[nr]= (float)((-b+p)/(2*a)); + /* driver must use bones from same armature... */ + cdriver->id= cdriver->id2= (ID *)idriver->ob; - if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1; - else return nr; - } - else if (p == 0) { - o[0]= (float)(-b / (2 * a)); - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; - } - } - else if (b != 0.0) { - o[0]= (float)(-c/b); - - if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1; - else return 0; - } - else if (c == 0.0) { - o[0]= 0.0; - return 1; - } - - return 0; - } -} - -void berekeny (float f1, float f2, float f3, float f4, float *o, int b) -{ - float t, c0, c1, c2, c3; - int a; - - c0= f1; - c1= 3.0f * (f2 - f1); - c2= 3.0f * (f1 - 2.0f*f2 + f3); - c3= f4 - f1 + 3.0f * (f2 - f3); - - for (a=0; a < b; a++) { - t= o[a]; - o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3; - } -} - -void berekenx (float *f, float *o, int b) -{ - float t, c0, c1, c2, c3; - int a; - - c0= f[0]; - c1= 3 * (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; - } -} - -/* ***************************** 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 parmat[4][4], offs_bone[4][4], imat[4][4]; - float diff_mat[4][4]; - - /* get first the parent + bone transform in parmat */ - if (pchan->parent) { - /* bone transform itself */ - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); - - /* 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 */ - Mat4Invert(imat, parmat); - } - 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); - - /* extract relevant components */ - if (loc) - VECCOPY(loc, diff_mat[3]); - if (eul) - Mat4ToEul(diff_mat, eul); - if (size) - Mat4ToSize(diff_mat, size); -} - -/* evaluate an IPO-driver to get a 'time' value to use instead of "ipotime" - * - "ipotime" is the frame at which IPO-curve is being evaluated - * - has to return a float value - */ -static float eval_driver (IpoDriver *driver, float ipotime) -{ -#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) ) - { - return 0.0f; - } - - /* this evaluates the expression using Python,and returns its result: - * - on errors it reports, then returns 0.0f - */ - return BPY_pydriver_eval(driver); - } - else -#endif /* DISABLE_PYTHON */ - { - Object *ob= driver->ob; - - /* must have an object to evaluate */ - if (ob == NULL) - return 0.0f; - - /* if a proxy, use the proxy source*/ - if (ob->proxy_from) - ob= ob->proxy_from; - - /* use given object as driver */ - if (driver->blocktype == ID_OB) { - /* depsgraph failure: ob ipos are calculated in where_is_object, this might get called too late */ - if ((ob->ipo) && (ob->ctime != ipotime)) { - /* calculate the value of relevant channel on the Object, but do not write the value - * calculated on to the Object but onto "ipotime" instead + /* paths for the two targets get the pointers to the relevant Pose-Channels + * - return pointers to Pose-Channels not rotation channels, as calculation code is picky + * - old bone names were stored in same var, in idriver->name + * + * - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and + * providing a name for 'actname' will automatically imply Pose-Channel with name 'actname' */ - calc_ipo_spec(ob->ipo, driver->adrcode, &ipotime); - return ipotime; + cdriver->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL); + cdriver->rna_path2= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL); } - - /* return the value of the relevant channel */ - switch (driver->adrcode) { - case OB_LOC_X: - return ob->loc[0]; - case OB_LOC_Y: - return ob->loc[1]; - case OB_LOC_Z: - return ob->loc[2]; - case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[0]/(M_PI_2/9.0) ); - case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[1]/(M_PI_2/9.0) ); - case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( ob->rot[2]/(M_PI_2/9.0) ); - case OB_SIZE_X: - return ob->size[0]; - case OB_SIZE_Y: - return ob->size[1]; - case OB_SIZE_Z: - return ob->size[2]; - } - } - - /* use given pose-channel as driver */ - else { /* ID_AR */ - bPoseChannel *pchan= get_pose_channel(ob->pose, driver->name); - - /* must have at least 1 bone to use */ - if (pchan && pchan->bone) { - /* rotation difference is not a simple driver (i.e. value drives value), but the angle between 2 bones is driving stuff... - * - the name of the second pchan is also stored in driver->name, but packed after the other one by DRIVER_NAME_OFFS chars - */ - if (driver->adrcode == OB_ROT_DIFF) { - bPoseChannel *pchan2= get_pose_channel(ob->pose, driver->name+DRIVER_NAME_OFFS); - - if (pchan2 && pchan2->bone) { - float q1[4], q2[4], quat[4], angle; - - Mat4ToQuat(pchan->pose_mat, q1); - Mat4ToQuat(pchan2->pose_mat, q2); - - QuatInv(q1); - QuatMul(quat, q1, q2); - angle = 2.0f * (saacos(quat[0])); - angle= ABS(angle); - - return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle); - } - } + else { + /* 'standard' driver */ + cdriver->type= DRIVER_TYPE_CHANNEL; + cdriver->id= (ID *)idriver->ob; - /* 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) { - case OB_LOC_X: - return loc[0]; + switch (idriver->adrcode) { + case OB_LOC_X: /* x,y,z location are quite straightforward */ + cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &cdriver->array_index); + break; case OB_LOC_Y: - return loc[1]; + cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &cdriver->array_index); + break; case OB_LOC_Z: - return loc[2]; - case OB_ROT_X: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[0]/(M_PI_2/9.0) ); - case OB_ROT_Y: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[1]/(M_PI_2/9.0) ); - case OB_ROT_Z: /* hack: euler rotations are divided by 10 deg to fit on same axes as other channels */ - return (float)( eul[2]/(M_PI_2/9.0) ); - case OB_SIZE_X: - return size[0]; + cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &cdriver->array_index); + break; + + case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */ + cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &cdriver->array_index); + break; case OB_SIZE_Y: - return size[1]; + cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &cdriver->array_index); + break; case OB_SIZE_Z: - return size[2]; + cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &cdriver->array_index); + break; + + case OB_ROT_X: /* rotation - we need to be careful with this... XXX (another reason why we need eulers) */ + case OB_ROT_Y: + case OB_ROT_Z: + { + // XXX this is not yet a 1:1 map, since we'd need euler rotations to make this work nicely (unless we make some hacks) + // XXX -1 here is a special hack... + cdriver->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL); + cdriver->array_index= idriver->adrcode - OB_ROT_X; } + break; } } } - } + else { + /* ID_OB */ + cdriver->type= DRIVER_TYPE_CHANNEL; + cdriver->id= (ID *)idriver->ob; + cdriver->rna_path= get_rna_access(ID_OB, idriver->adrcode, idriver->name, NULL, &cdriver->array_index); + } + } - /* return 0.0f, as couldn't find relevant data to use */ - return 0.0f; + /* free old driver */ + MEM_freeN(idriver); + + /* return the new one */ + return cdriver; } -/* evaluate and return the value of the given IPO-curve at the specified frame ("evaltime") */ -float eval_icu (IpoCurve *icu, float evaltime) +/* Convert IPO-Curve to F-Curve (including Driver data), and free any of the old data that + * is not relevant, BUT do not free the IPO-Curve itself... + * actname: name of Action-Channel (if applicable) that IPO-Curve's IPO-block belonged to + * constname: name of Constraint-Channel (if applicable) that IPO-Curve's IPO-block belonged to + */ +static FCurve *icu_to_fcu (IpoCurve *icu, char *actname, char *constname) { - float cvalue = 0.0f; + FCurve *fcu; + int i= 0; - /* 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 - */ + /* allocate memory for a new F-Curve */ + fcu= MEM_callocN(sizeof(FCurve), "FCurve"); + + /* convert driver - will free the old one... */ if (icu->driver) { - /* ipotime now serves as input for the curve */ - evaltime= cvalue= eval_driver(icu->driver, evaltime); + fcu->driver= idriver_to_cdriver(icu->driver); + icu->driver= NULL; } - /* there are keyframes (in the form of BezTriples) which can be interpolated between */ + /* convert keyframes + * - beztriples and bpoints are mutually exclusive, so we won't have both at the same time + * - beztriples are more likely to be encountered as they are keyframes (the other type wasn't used yet) + */ + // XXX we need to cope with the nasty old 'bitflag' curves... that will be a task for later + fcu->totvert= icu->totvert; + 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.0f; - int a, b; + /* allocate new array for keyframes/beztriples */ + fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples"); - /* get pointers */ - a= icu->totvert-1; - prevbezt= icu->bezt; - bezt= prevbezt+1; - lastbezt= prevbezt + a; - - /* extrapolation mode is 'cyclic' - find relative place within a cycle */ - if (icu->extrap & IPO_CYCL) { - /* ofs is start frame of cycle */ - ofs= prevbezt->vec[1][0]; - - /* calculate period and amplitude (total height) of a cycle */ - cycdx= lastbezt->vec[1][0] - prevbezt->vec[1][0]; - cycdy= lastbezt->vec[1][1] - prevbezt->vec[1][1]; + /* check if we need to set interpolation settings (thus doing it the 'slow' way) */ + if (icu->ipo != IPO_MIXED) { + BezTriple *dst, *src; - /* 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; - } + /* loop through copying all BezTriples, as we need to set interpolation settings too */ + for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) { + /* firstly, copy BezTriple data */ + *dst= *src; - /* calculate where in the cycle we are (overwrite evaltime to reflect this) */ - evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs); - if (evaltime < ofs) evaltime += cycdx; - } - } - - /* evaluation time at or past endpoints? */ - if (prevbezt->vec[1][0] >= evaltime) { - /* before or on first keyframe */ - if ((icu->extrap & IPO_DIR) && (prevbezt->ipo != IPO_CONST)) { - /* linear or bezier interpolation */ - if (prevbezt->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 { - /* constant (IPO_HORIZ) extrapolation or constant interpolation, - * so just extend first keyframe's value - */ - cvalue= prevbezt->vec[1][1]; - } - } - else if (lastbezt->vec[1][0] <= evaltime) { - /* after or on last keyframe */ - if( (icu->extrap & IPO_DIR) && (lastbezt->ipo != IPO_CONST)) { - /* linear or bezier interpolation */ - if (lastbezt->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 { - /* constant (IPO_HORIZ) extrapolation or constant interpolation, - * so just extend last keyframe's value - */ - cvalue= lastbezt->vec[1][1]; + /* now copy interpolation from curve */ + dst->ipo= icu->ipo; } } else { - /* evaltime occurs somewhere in the middle of the curve */ - 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 (prevbezt->ipo == IPO_CONST) { - /* constant (evaltime not relevant, so no interpolation needed) */ - cvalue= prevbezt->vec[1][1]; - } - else if (prevbezt->ipo == IPO_LIN) { - /* linear - interpolate between values of the two keyframes */ - fac= bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac= (evaltime - prevbezt->vec[1][0]) / fac; - cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1])); - } - else - cvalue= prevbezt->vec[1][1]; - } - else { - /* bezier interpolation */ - /* v1,v2 are the first keyframe and its 2nd handle */ - v1[0]= prevbezt->vec[1][0]; - v1[1]= prevbezt->vec[1][1]; - v2[0]= prevbezt->vec[2][0]; - v2[1]= prevbezt->vec[2][1]; - /* v3,v4 are the last keyframe's 1st handle + the last keyframe */ - v3[0]= bezt->vec[0][0]; - v3[1]= bezt->vec[0][1]; - v4[0]= bezt->vec[1][0]; - v4[1]= bezt->vec[1][1]; - - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue= opl[0]; - break; - } - } - } - } + /* interpolation already set (from AnimSys2 branch) */ + memcpy(fcu->bezt, icu->bezt, sizeof(BezTriple)*fcu->totvert); } - - /* apply y-offset (for 'cyclic extrapolation') to calculated value */ - cvalue += cycyofs; } - - /* clamp evaluated value to lie within allowable value range for this channel */ - if (icu->ymin < icu->ymax) { - CLAMP(cvalue, icu->ymin, icu->ymax); + else if (icu->bp) { + /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */ + //BPoint *bp; + //FPoint *fpt; } - /* return evaluated value */ - return cvalue; -} - -/* ------------------- IPO-Block/Curve Calculation - General API ----------------------- */ - -/* calculate the value of the given IPO-curve at the current frame, and set its curval */ -void calc_icu (IpoCurve *icu, float ctime) -{ - /* calculate and set curval (evaluates driver too) */ - icu->curval= eval_icu(icu, ctime); -} - -/* calculate for the current frame, all IPO-curves in IPO-block that can be evaluated - * - icu->curval is set for all IPO-curves which are evaluated! - */ -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); + /* get rna-path + * - we will need to set the 'disabled' flag if no path is able to be made (for now) + */ + fcu->rna_path= get_rna_access(icu->blocktype, icu->adrcode, actname, constname, &fcu->array_index); + if (fcu->rna_path == NULL) + fcu->flag |= FCURVE_DISABLED; + + /* copy flags */ + if (icu->flag & IPO_VISIBLE) fcu->flag |= FCURVE_VISIBLE; + if (icu->flag & IPO_SELECT) fcu->flag |= FCURVE_SELECTED; + if (icu->flag & IPO_ACTIVE) fcu->flag |= FCURVE_ACTIVE; + if (icu->flag & IPO_MUTE) fcu->flag |= FCURVE_MUTED; + if (icu->flag & IPO_PROTECT) fcu->flag |= FCURVE_PROTECTED; + if (icu->flag & IPO_AUTO_HORIZ) fcu->flag |= FCURVE_AUTO_HANDLES; + + /* set extrapolation */ + switch (icu->extrap) { + case IPO_HORIZ: /* constant extrapolation */ + case IPO_DIR: /* linear extrapolation */ + { + /* just copy, as the new defines match the old ones... */ + fcu->extend= icu->extrap; } - } -} - -/* ------------------- IPO-Block/Curve Calculation - Special Hacks ----------------------- */ - -/* Calculate and return the value of the 'Time' Ipo-Curve from an Object, - * OR return the current time if not found - * - used in object.c -> bsystem_time() - */ -float calc_ipo_time (Ipo *ipo, float ctime) -{ - /* only Time IPO from Object IPO-blocks are relevant */ - if ((ipo) && (ipo->blocktype == ID_OB)) { - IpoCurve *icu= find_ipocurve(ipo, OB_TIME); - - /* only calculate (and set icu->curval) for time curve */ - if (icu) { - calc_icu(icu, ctime); - return (10.0f * icu->curval); + break; + + case IPO_CYCL: /* cyclic extrapolation */ + case IPO_CYCLX: /* cyclic extrapolation + offset */ + { + /* Add a new FModifier (Cyclic) instead of setting extend value + * as that's the new equivilant of that option. + */ + FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES); + FMod_Cycles *data= (FMod_Cycles *)fcm->data; + + /* if 'offset' one is in use, set appropriate settings */ + if (icu->extrap == IPO_CYCLX) + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC_OFFSET; + else + data->before_mode= data->after_mode= FCM_EXTRAPOLATE_CYCLIC; } + break; } - /* no appropriate time-curve found */ - return ctime; + /* return new F-Curve */ + return fcu; } -/* 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! +/* Convert IPO-block (i.e. all its IpoCurves) for some ID to the new system + * This assumes that AnimData has been added already. Separation of drivers + * from animation data is accomplished here too... */ -short calc_ipo_spec (Ipo *ipo, int adrcode, float *ctime) +static void ipo_to_animdata (ID *id, Ipo *ipo, char *actname, char *constname) { - IpoCurve *icu= find_ipocurve(ipo, adrcode); + AnimData *adt= BKE_animdata_from_id(id); + bAction *act= adt->action; + //bActionGroup *grp; + IpoCurve *icu, *icn; + FCurve *fcu; + + /* sanity check */ + if ELEM(NULL, id, ipo) + return; + + printf("ipo to animdata - ID:%s, IPO:%s, actname:%s constname:%s curves:%d \n", + id->name+2, ipo->id.name+2, (actname)?actname:"<None>", (constname)?constname:"<None>", + BLI_countlist(&ipo->curve)); + + /* validate actname and constname + * - clear actname if it was one of the generic <builtin> ones (i.e. 'Object', or 'Shapes') + * - actname can then be used to assign F-Curves in Action to Action Groups + * (i.e. thus keeping the benefits that used to be provided by Action Channels for grouping + * F-Curves for bones). This may be added later... for now let's just dump without them... + */ + if (actname) { + if ((GS(id->name) == ID_OB) && (strcmp(actname, "Object") == 0)) + actname= NULL; + if ((GS(id->name) == ID_OB) && (strcmp(actname, "Shape") == 0)) + actname= NULL; + } - /* 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 + /* loop over IPO-Curves, freeing as we progress */ + for (icu= ipo->curve.first; icu; icu= icn) { + /* get link to next (for later) */ + icn= icu->next; + + /* convert IPO-Curve to F-Curve + * NOTE: this frees any of the old data stored in the IPO-Curve that isn't needed anymore... */ - if ((icu->flag & (IPO_LOCK|IPO_MUTE))==0) - calc_icu(icu, *ctime); + // XXX we need to cope with the nasty old 'bitflag' curves... that will be a task for later + // we will need to create a few new curves when doing so, and will need to sift through the keyframes to add relevant data + fcu= icu_to_fcu(icu, actname, constname); + + /* conversion path depends on whether it's a driver or not */ + if (fcu->driver == NULL) { + /* try to get action */ + if (adt->action == NULL) + act= adt->action= add_empty_action("ConvertedAction"); // XXX we need a better name for this... + + /* add F-Curve to action */ + BLI_addtail(&act->curves, fcu); + } + else { + /* add F-Curve to AnimData's drivers */ + BLI_addtail(&adt->drivers, fcu); + } - /* value resulting from calculations is written into ctime! */ - *ctime= icu->curval; - return 1; + /* free this IpoCurve now that it's been converted */ + BLI_freelinkN(&ipo->curve, icu); } - - /* 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) +/* Convert Action-block to new system + * NOTE: we need to be careful here, as same data-structs are used for new system too! */ -void execute_ipo (ID *id, Ipo *ipo) +static void action_to_animdata (ID *id, bAction *act) { - IpoCurve *icu; - void *poin; - int type; + AnimData *adt= BKE_animdata_from_id(id); + bActionChannel *achan, *achann; + bConstraintChannel *conchan, *conchann; - /* don't do anything without an IPO block */ - if (ipo == NULL) + /* only continue if there are Action Channels (indicating unconverted data) */ + if (ELEM(NULL, adt, act->chanbase.first)) return; - - /* loop over IPO Curves, getting pointer to var to affect, and write into that pointer */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - poin= get_ipo_poin(id, icu, &type); - if (poin) write_ipo_poin(poin, type, icu->curval); + + /* get rid of all Action Groups */ + // XXX this is risky if there's some old, some new data in the Action... + if (act->groups.first) + BLI_freelistN(&act->groups); + + /* check if we need to set this Action as the AnimData's action */ + if (adt->action == NULL) { + /* set this Action as AnimData's Action */ + adt->action= act; } -} - -/* 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 */ - for (icu= achan->ipo->curve.first; icu; icu= icu->next) { - void *poin= get_pchan_ipo_poin(pchan, icu->adrcode); + /* loop through Action-Channels, converting data, freeing as we go */ + for (achan= act->chanbase.first; achan; achan= achann) { + /* get pointer to next Action Channel */ + achann= achan->next; + + /* convert Action Channel's IPO data */ + if (achan->ipo) { + ipo_to_animdata(id, achan->ipo, achan->name, NULL); + achan->ipo->id.us--; + achan->ipo= NULL; + } + + /* convert constraint channel IPO-data */ + for (conchan= achan->constraintChannels.first; conchan; conchan= conchann) { + /* get pointer to next Constraint Channel */ + conchann= conchan->next; - if (poin) { - /* only euler-rotations are of type float-degree, all others are 'float' only */ - if (ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) - write_ipo_poin(poin, IPO_FLOAT_DEGR, icu->curval); - else - write_ipo_poin(poin, IPO_FLOAT, icu->curval); + /* convert Constraint Channel's IPO data */ + if (conchan->ipo) { + ipo_to_animdata(id, conchan->ipo, achan->name, conchan->name); + conchan->ipo->id.us--; + conchan->ipo= NULL; } + + /* free Constraint Channel */ + BLI_freelinkN(&achan->constraintChannels, conchan); } - } -} - - -/* --------------------- 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 (Scene *scene, Ipo *ipo) -{ - if (ipo) { - float ctime= frame_to_float(scene, scene->r.cfra); - /* calculate values, then flush to all users of this IPO block */ - calc_ipo(ipo, ctime); - do_ipo_nocalc(scene, ipo); + /* free Action Channel */ + BLI_freelinkN(&act->chanbase, achan); } } -/* Calculate values for given Material's IPO block, then flush to given Material only */ -void do_mat_ipo (Scene *scene, Material *ma) -{ - float ctime; - - if (ELEM(NULL, ma, ma->ipo)) - return; - - ctime= frame_to_float(scene, 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); -} +/* *************************************************** */ +/* External API - Only Called from do_versions() */ -/* 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 +/* Called from do_versions() in readfile.c to convert the old 'IPO/adrcode' system + * to the new 'Animato/RNA' system. + * + * The basic method used here, is to loop over datablocks which have IPO-data, and + * add those IPO's to new AnimData blocks as Actions. + * Action/NLA data only works well for Objects, so these only need to be checked for there. + * + * Data that has been converted should be freed immediately, which means that it is immediately + * clear which datablocks have yet to be converted, and also prevent freeing errors when we exit. */ -void do_ob_ipo (Scene *scene, Object *ob) +// XXX currently done after all file reading... +void do_versions_ipos_to_animato(Main *main) { - float ctime; - unsigned int lay; + ID *id; + AnimData *adt; - if (ob->ipo == NULL) + if (main == NULL) { + printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n"); return; - - /* do not set ob->ctime here: for example when parent in invisible layer */ - ctime= bsystem_time(scene, ob, (float) 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(scene->id.name+2, ob->id.name+6)==0) { - scene->lay= ob->lay; - //XXX copy_view3d_lock(0); - /* no redraw here! creates too many calls */ - } } -} - -/* Only execute those IPO-Curves with drivers, on the current frame, for the given Object - * - TODO: Drivers should really be made separate from standard anim channels - */ -void do_ob_ipodrivers (Object *ob, Ipo *ipo, float ctime) -{ - IpoCurve *icu; - void *poin; - int type; - - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->driver) { - icu->curval= eval_icu(icu, ctime); - - poin= get_ipo_poin((ID *)ob, icu, &type); - if (poin) write_ipo_poin(poin, type, icu->curval); - } + + /* only convert if version is right */ + // XXX??? + if (main->versionfile >= 250) { + printf("WARNING: Animation data too new to convert (Version %d) \n", main->versionfile); + return; } -} - -/* Special variation to calculate IPO values for Sequence + perform other stuff */ -void do_seq_ipo (Scene *scene, Sequence *seq, int cfra) -{ - float ctime, div; + else + printf("INFO: Converting to Animato... \n"); // xxx debug + - /* seq_ipo has an exception: calc both fields immediately */ - if (seq->ipo) { - if ((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) { - ctime = frame_to_float(scene, cfra); - div = 1.0; - } - else { - ctime= frame_to_float(scene, cfra - seq->startdisp); - div= (seq->enddisp - seq->startdisp) / 100.0f; - if (div == 0.0) return; - } + /* objects */ + for (id= main->object.first; id; id= id->next) { + Object *ob= (Object *)id; + bPoseChannel *pchan; + bConstraint *con; + bConstraintChannel *conchan, *conchann; - /* 2nd field */ - calc_ipo(seq->ipo, (ctime+0.5f)/div); - execute_ipo((ID *)seq, seq->ipo); - seq->facf1= seq->facf0; + printf("\tconverting ob %s \n", id->name+2); - /* 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 (struct Scene *scene, 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(scene, ob); - } - break; - case ID_MA: - for (ma= G.main->mat.first; ma; ma= ma->id.next) { - if (ma->ipo == ipo) execute_ipo((ID *)ma, ipo); - } - break; - case ID_TE: - for (tex= G.main->tex.first; tex; tex= tex->id.next) { - if (tex->ipo == ipo) execute_ipo((ID *)tex, ipo); - } - break; - case ID_WO: - for (wo= G.main->world.first; wo; wo= wo->id.next) { - if (wo->ipo == ipo) execute_ipo((ID *)wo, ipo); - } - break; - case ID_LA: - for (la= G.main->lamp.first; la; la= la->id.next) { - if (la->ipo == ipo) execute_ipo((ID *)la, ipo); - } - break; - case ID_CA: - for (ca= G.main->camera.first; ca; ca= ca->id.next) { - if (ca->ipo == ipo) execute_ipo((ID *)ca, ipo); - } - break; - case ID_SO: - for (snd= G.main->sound.first; snd; snd= snd->id.next) { - if (snd->ipo == ipo) execute_ipo((ID *)snd, ipo); + /* check if object has any animation data */ + if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* IPO first */ + if (ob->ipo) { + ipo_to_animdata(id, ob->ipo, NULL, NULL); + ob->ipo->id.us--; + ob->ipo= NULL; + } + + /* now Action */ + if (ob->action) { + action_to_animdata(id, ob->action); + + /* only decrease usercount if this Action isn't now being used by AnimData */ + if (ob->action != adt->action) { + ob->action->id.us--; + ob->action= NULL; + } + } + + /* finally NLA */ + // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!) } - break; - } -} - -/* 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 (Scene *scene) -{ - 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(scene, scene->r.cfra); - - /* this exception cannot be depgraphed yet... what todo with objects in other layers?... */ - for (base= 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(scene, ob); - base->lay= ob->lay; + /* check PoseChannels for constraints with local data */ + if (ob->pose) { + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + for (con= pchan->constraints.first; con; con= con->next) { + /* if constraint has own IPO, convert add these to Object + * (NOTE: they're most likely to be drivers too) + */ + + /* check for Action Constraint */ + // XXX do we really want to do this here? + } + } } - } - - /* layers for the set...*/ - if (scene->set) { - for (base= scene->set->base.first; base; base= base->next) { - Object *ob= base->object; + + /* check constraint channels - we need to remove them anyway... */ + for (conchan= ob->constraintChannels.first; conchan; conchan= conchann) { + /* get pointer to next Constraint Channel */ + conchann= conchan->next; - if (has_ipo_code(ob->ipo, OB_LAY)) { - do_ob_ipo(scene, ob); - base->lay= ob->lay; + /* convert Constraint Channel's IPO data */ + if (conchan->ipo) { + ipo_to_animdata(id, conchan->ipo, NULL, conchan->name); + conchan->ipo->id.us--; + conchan->ipo= NULL; } + + /* free Constraint Channel */ + BLI_freelinkN(&ob->constraintChannels, conchan); } } - /* 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); + /* shapekeys */ + for (id= main->key.first; id; id= id->next) { + Key *key= (Key *)id; + + printf("\tconverting key %s \n", id->name+2); + + /* we're only interested in the IPO + * NOTE: for later, it might be good to port these over to Object instead, as many of these + * are likely to be drivers, but it's hard to trace that from here, so move this to Ob loop? + */ + if (key->ipo) { + /* Add AnimData block */ + adt= BKE_id_add_animdata(id); + + /* Convert Shapekey data... */ + ipo_to_animdata(id, key->ipo, NULL, NULL); + key->ipo->id.us--; + key->ipo= NULL; } } - - /* 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); - } + // XXX add other types too... - /* 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= 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 <= scene->r.cfra+2) && - (seq->enddisp>scene->r.cfra) && - (seq->ipo) ) - { - do_seq_ipo(scene, seq, scene->r.cfra); - } - } - } + printf("INFO: animato convert done \n"); // xxx debug } -/* --------------------- 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); - } - } - } -} +#if 0 // XXX old animation system /* ***************************** IPO - DataAPI ********************************* */ @@ -1824,77 +823,6 @@ void clear_delta_obipo(Ipo *ipo) /* --------------------- Get Pointer API ----------------------------- */ -/* get pointer to pose-channel's channel, but set appropriate flags first */ -// TODO: most channels (except euler rots, which are float-degr) are floats, so do we need type arg? -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_EUL_X: - poin= &(pchan->eul[0]); - pchan->flag |= POSE_ROT; - //type= IPO_FLOAT_DEGR; - break; - case AC_EUL_Y: - poin= &(pchan->eul[1]); - pchan->flag |= POSE_ROT; - //type= IPO_FLOAT_DEGR; - break; - case AC_EUL_Z: - poin= &(pchan->eul[2]); - pchan->flag |= POSE_ROT; - //type= IPO_FLOAT_DEGR; - 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 ) { @@ -2024,83 +952,6 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type) /* data is divided into 'blocktypes' based on ID-codes */ switch (GS(id->name)) { - case ID_OB: /* object channels ----------------------------- */ - { - Object *ob= (Object *)id; - - switch (icu->adrcode) { - case OB_LOC_X: - poin= &(ob->loc[0]); break; - case OB_LOC_Y: - poin= &(ob->loc[1]); break; - case OB_LOC_Z: - poin= &(ob->loc[2]); break; - case OB_DLOC_X: - poin= &(ob->dloc[0]); break; - case OB_DLOC_Y: - poin= &(ob->dloc[1]); break; - case OB_DLOC_Z: - poin= &(ob->dloc[2]); break; - - case OB_ROT_X: - poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break; - case OB_ROT_Y: - poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break; - case OB_ROT_Z: - poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_X: - poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_Y: - poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break; - case OB_DROT_Z: - poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break; - - case OB_SIZE_X: - poin= &(ob->size[0]); break; - case OB_SIZE_Y: - poin= &(ob->size[1]); break; - case OB_SIZE_Z: - poin= &(ob->size[2]); break; - case OB_DSIZE_X: - poin= &(ob->dsize[0]); break; - case OB_DSIZE_Y: - poin= &(ob->dsize[1]); break; - case OB_DSIZE_Z: - poin= &(ob->dsize[2]); break; - - case OB_LAY: - poin= &(ob->lay); *type= IPO_INT_BIT; break; - - case OB_COL_R: - poin= &(ob->col[0]); break; - case OB_COL_G: - poin= &(ob->col[1]); break; - case OB_COL_B: - poin= &(ob->col[2]); break; - case OB_COL_A: - poin= &(ob->col[3]); break; - - case OB_PD_FSTR: - if (ob->pd) poin= &(ob->pd->f_strength); - break; - case OB_PD_FFALL: - if (ob->pd) poin= &(ob->pd->f_power); - break; - case OB_PD_SDAMP: - if (ob->pd) poin= &(ob->pd->pdef_damp); - break; - case OB_PD_RDAMP: - if (ob->pd) poin= &(ob->pd->pdef_rdamp); - break; - case OB_PD_PERM: - if (ob->pd) poin= &(ob->pd->pdef_perm); - break; - case OB_PD_FMAXD: - if (ob->pd) poin= &(ob->pd->maxdist); - break; - } - } - break; case ID_MA: /* material channels ----------------------------- */ { Material *ma= (Material *)id; @@ -2193,35 +1044,6 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type) 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; - } - } - break; - case ID_CU: /* curve channels ----------------------------- */ - { - poin= &(icu->curval); - } - 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; @@ -2455,482 +1277,5 @@ void *get_ipo_poin (ID *id, IpoCurve *icu, int *type) return poin; } -/* --------------------- IPO-Curve Limits ----------------------------- */ - -/* set limits for IPO-curve - * Note: must be synced with UI and PyAPI - */ -void set_icu_vars (IpoCurve *icu) -{ - /* defaults. 0.0 for y-extents makes these ignored */ - icu->ymin= icu->ymax= 0.0; - icu->ipo= IPO_BEZ; - - switch (icu->blocktype) { - case ID_OB: /* object channels ----------------------------- */ - { - if (icu->adrcode == OB_LAY) { - icu->ipo= IPO_CONST; - icu->vartype= IPO_BITS; - } - } - break; - case ID_MA: /* material channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case MA_HASIZE: - icu->ymax= 10000.0; break; - case MA_HARD: - icu->ymax= 511.0; break; - case MA_SPEC: - icu->ymax= 2.0; break; - case MA_MODE: - icu->ipo= IPO_CONST; - icu->vartype= IPO_BITS; break; - case MA_RAYM: - icu->ymax= 1.0; break; - case MA_TRANSLU: - icu->ymax= 1.0; break; - case MA_IOR: - icu->ymin= 1.0; - icu->ymax= 3.0; break; - case MA_FRESMIR: - icu->ymax= 5.0; break; - case MA_FRESMIRI: - icu->ymin= 1.0; - icu->ymax= 5.0; break; - case MA_FRESTRA: - icu->ymax= 5.0; break; - case MA_FRESTRAI: - icu->ymin= 1.0; - icu->ymax= 5.0; break; - case MA_ADD: - icu->ymax= 1.0; break; - case MA_EMIT: - icu->ymax= 2.0; break; - default: - icu->ymax= 1.0; break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 1000.0; - icu->ymin= -1000.0; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0; - break; - case MAP_NORF: - icu->ymax= 25.0; - break; - } - } - } - break; - case ID_TE: /* texture channels ----------------------------- */ - { - switch (icu->adrcode & (MA_MAP1-1)) { - case TE_NSIZE: - icu->ymin= 0.0001f; - icu->ymax= 2.0f; - break; - case TE_NDEPTH: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_NTYPE: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 1.0f; - break; - case TE_TURB: - icu->ymax= 200.0f; - break; - case TE_VNW1: - case TE_VNW2: - case TE_VNW3: - case TE_VNW4: - icu->ymax= 2.0f; - icu->ymin= -2.0f; - break; - case TE_VNMEXP: - icu->ymax= 10.0f; - icu->ymin= 0.01f; - break; - case TE_VN_DISTM: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_VN_COLT: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 3.0f; - break; - case TE_ISCA: - icu->ymax= 10.0f; - icu->ymin= 0.01f; - break; - case TE_DISTA: - icu->ymax= 10.0f; - break; - case TE_MG_TYP: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 6.0f; - break; - case TE_MGH: - icu->ymin= 0.0001f; - icu->ymax= 2.0f; - break; - case TE_MG_LAC: - case TE_MG_OFF: - case TE_MG_GAIN: - icu->ymax= 6.0f; break; - case TE_MG_OCT: - icu->ymax= 8.0f; break; - case TE_N_BAS1: - case TE_N_BAS2: - icu->vartype= IPO_SHORT; - icu->ipo= IPO_CONST; - icu->ymax= 8.0f; - break; - case TE_COL_R: - icu->ymax= 0.0f; break; - case TE_COL_G: - icu->ymax= 2.0f; break; - case TE_COL_B: - icu->ymax= 2.0f; break; - case TE_BRIGHT: - icu->ymax= 2.0f; break; - case TE_CONTRA: - icu->ymax= 5.0f; break; - } - } - break; - case ID_SEQ: /* sequence channels ----------------------------- */ - { - icu->ymax= 1.0f; - } - break; - case ID_CU: /* curve channels ----------------------------- */ - { - icu->ymax= 1.0f; - } - break; - case ID_WO: /* world channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case WO_EXPOS: - icu->ymax= 5.0f; break; - - case WO_MISTDI: - case WO_MISTSTA: - case WO_MISTHI: - case WO_STARDIST: - case WO_STARSIZE: - break; - - default: - icu->ymax= 1.0f; - break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 100.0f; - icu->ymin= -100.0f; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_NORF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0f; - } - } - } - break; - case ID_LA: /* lamp channels ----------------------------- */ - { - if (icu->adrcode < MA_MAP1) { - switch (icu->adrcode) { - case LA_ENERGY: - case LA_DIST: - break; - - case LA_COL_R: - case LA_COL_G: - case LA_COL_B: - case LA_SPOTBL: - case LA_QUAD1: - case LA_QUAD2: - icu->ymax= 1.0f; break; - - case LA_SPOTSI: - icu->ymax= 180.0f; break; - - case LA_HALOINT: - icu->ymax= 5.0f; break; - } - } - else { - switch (icu->adrcode & (MA_MAP1-1)) { - case MAP_OFS_X: - case MAP_OFS_Y: - case MAP_OFS_Z: - case MAP_SIZE_X: - case MAP_SIZE_Y: - case MAP_SIZE_Z: - icu->ymax= 100.0f; - icu->ymin= -100.0f; - break; - case MAP_R: - case MAP_G: - case MAP_B: - case MAP_DVAR: - case MAP_COLF: - case MAP_NORF: - case MAP_VARF: - case MAP_DISP: - icu->ymax= 1.0f; - } - } - } - break; - case ID_CA: /* camera channels ----------------------------- */ - { - switch (icu->adrcode) { - case CAM_LENS: - icu->ymin= 1.0f; - icu->ymax= 1000.0f; - break; - case CAM_STA: - icu->ymin= 0.001f; - break; - case CAM_END: - icu->ymin= 0.1f; - break; - - case CAM_YF_APERT: - icu->ymin = 0.0f; - icu->ymax = 2.0f; - break; - case CAM_YF_FDIST: - icu->ymin = 0.0f; - icu->ymax = 5000.0f; - break; - - case CAM_SHIFT_X: - case CAM_SHIFT_Y: - icu->ymin= -2.0f; - icu->ymax= 2.0f; - break; - } - } - break; - case ID_SO: /* sound channels ----------------------------- */ - { - switch (icu->adrcode) { - case SND_VOLUME: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case SND_PITCH: - icu->ymin= -12.0f; - icu->ymin= 12.0f; - break; - case SND_PANNING: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case SND_ATTEN: - icu->ymin= 0.0f; - icu->ymin= 1.0f; - break; - } - } - break; - case ID_PA: /* particle channels ----------------------------- */ - { - switch (icu->adrcode) { - case PART_EMIT_LIFE: - case PART_SIZE: - case PART_KINK_FREQ: - case PART_EMIT_VEL: - case PART_EMIT_AVE: - case PART_EMIT_SIZE: - icu->ymin= 0.0f; - break; - case PART_CLUMP: - icu->ymin= -1.0f; - icu->ymax= 1.0f; - break; - case PART_DRAG: - case PART_DAMP: - case PART_LENGTH: - icu->ymin= 0.0f; - icu->ymax= 1.0f; - break; - case PART_KINK_SHAPE: - icu->ymin= -0.999f; - icu->ymax= 0.999f; - break; - } - } - 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; -} - -/* --------------------- Pointer I/O API ----------------------------- */ - -/* write the given value directly into the given pointer */ -void write_ipo_poin (void *poin, int type, float val) -{ - /* Note: we only support a limited number of types, with the value - * to set needing to be cast to the appropriate type first - * -> (float to integer conversions could be slow) - */ - switch(type) { - case IPO_FLOAT: - *((float *)poin)= val; - break; - - case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */ - *((float *)poin)= (float)(val * M_PI_2 / 9.0); - break; - - case IPO_INT: - case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil! - case IPO_LONG: - *((int *)poin)= (int)val; - break; - - case IPO_SHORT: - case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil! - *((short *)poin)= (short)val; - break; - - case IPO_CHAR: - case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil! - *((char *)poin)= (char)val; - break; - } -} - -/* read the value from the pointer that was obtained */ -float read_ipo_poin (void *poin, int type) -{ - float val = 0.0; - - /* Note: we only support a limited number of types, with the value - * to set needing to be cast to the appropriate type first - * -> (int to float conversions may loose accuracy in rare cases) - */ - switch (type) { - case IPO_FLOAT: - val= *((float *)poin); - break; - - case IPO_FLOAT_DEGR: /* special hack for rotation so that it fits on same axis as other transforms */ - val= *( (float *)poin); - val = (float)(val / (M_PI_2/9.0)); - break; - - case IPO_INT: - case IPO_INT_BIT: // fixme... directly revealing bitflag combinations is evil! - case IPO_LONG: - val= (float)( *((int *)poin) ); - break; - - case IPO_SHORT: - case IPO_SHORT_BIT: // fixme... directly revealing bitflag combinations is evil! - val= *((short *)poin); - break; - - case IPO_CHAR: - case IPO_CHAR_BIT: // fixme... directly revealing bitflag combinations is evil - val= *((char *)poin); - break; - } - - /* return value */ - return val; -} - -// !!!!!!!!!!!!!!!!!!!!!!!!!!!! FIXME - BAD CRUFT WARNING !!!!!!!!!!!!!!!!!!!!!!! - - -/* ***************************** IPO <--> GameEngine Interface ********************************* */ - -/* channels is max 32 items, allocated by calling function */ -short IPO_GetChannels (Ipo *ipo, IPO_Channel *channels) -{ - IpoCurve *icu; - int total = 0; - - /* don't do anything with no IPO-block */ - if (ipo == NULL) - return 0; - - /* 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; - - /* 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) -{ - /* don't evaluate if no IPO to use */ - if (ipo == NULL) - return 0; - - /* only calculate the specified channel */ - calc_ipo_spec(ipo, channel, &ctime); - - /* unapply rotation hack, as gameengine doesn't use it */ - if ((OB_ROT_X <= channel) && (channel <= OB_DROT_Z)) - ctime *= (float)(M_PI_2/9.0); - - /* return the value of this channel */ - return ctime; -} #endif // XXX old animation system diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 718ddf2dc96..8c5bac3019e 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" @@ -1367,6 +1368,10 @@ int do_ob_key(Scene *scene, Object *ob) execute_ipo((ID *)key, key->ipo); } #endif // XXX old animation system + /* do shapekey local drivers */ + float ctime= (float)scene->r.cfra; // XXX this needs to be checked + printf("ob %s - do shapekey drivers \n", ob->id.name+2); + BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS); if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data); else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index ecd6e22c3ef..b74406f3d3f 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -232,6 +232,7 @@ int set_listbasepointers(Main *main, ListBase **lb) /* BACKWARDS! also watch order of free-ing! (mesh<->mat) */ lb[a++]= &(main->ipo); + lb[a++]= &(main->action); // xxx moved here to avoid problems when freeing with animato (aligorith) lb[a++]= &(main->key); lb[a++]= &(main->nodetree); lb[a++]= &(main->image); @@ -244,7 +245,6 @@ int set_listbasepointers(Main *main, ListBase **lb) */ lb[a++]= &(main->armature); - lb[a++]= &(main->action); lb[a++]= &(main->mesh); lb[a++]= &(main->curve); @@ -490,7 +490,7 @@ void free_libblock(ListBase *lb, void *idv) free_camera((Camera*) id); break; case ID_IP: - /*free_ipo((Ipo *)id);*/ + free_ipo((Ipo *)id); break; case ID_KE: free_key((Key *)id); @@ -682,52 +682,6 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor } } - /* Silly routine, the only difference between the one - * above is that it only adds items with a matching - * blocktype... this should be unified somehow... - zr - */ -static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype) -{ - ID *id; - int i, nids; - - for (id= lb->first, nids= 0; id; id= id->next) { - Ipo *ipo= (Ipo*) id; - - if (ipo->blocktype==blocktype) - nids++; - } - - if (nids>MAX_IDPUP) { - BLI_dynstr_append(pupds, "DataBrowse %x-2"); - } else { - for (i=0, id= lb->first; id; id= id->next) { - Ipo *ipo= (Ipo*) id; - - if (ipo->blocktype==blocktype) { - char buf[32]; - - if (id==link) - *nr= i+1; - - if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.') - continue; - - get_flags_for_id(id, buf); - - BLI_dynstr_append(pupds, buf); - BLI_dynstr_append(pupds, id->name+2); - sprintf(buf, "%%x%d", i+1); - BLI_dynstr_append(pupds, buf); - - if(id->next) - BLI_dynstr_append(pupds, "|"); - - i++; - } - } - } -} /* used by headerbuttons.c buttons.c editobject.c editseq.c */ /* if nr==NULL no MAX_IDPUP, this for non-header browsing */ @@ -775,28 +729,6 @@ void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb } -/* only used by headerbuttons.c */ -void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype) -{ - DynStr *pupds= BLI_dynstr_new(); - - if (title) { - BLI_dynstr_append(pupds, title); - BLI_dynstr_append(pupds, "%t|"); - } - - if (extraops) { - BLI_dynstr_append(pupds, extraops); - if (BLI_dynstr_get_len(pupds)) - BLI_dynstr_append(pupds, "|"); - } - - IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype); - - *str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); -} - /* used by buttons.c library.c mball.c */ void splitIDname(char *name, char *left, int *nr) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2718981e398..15fde4420f0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2274,7 +2274,7 @@ void object_handle_update(Scene *scene, Object *ob) if(ob->recalc & OB_RECALC_OB) { - // printf("recalcob %s\n", ob->id.name+2); + printf("recalcob %s\n", ob->id.name+2); /* handle proxy copy for target */ if(ob->id.lib && ob->proxy_from) { @@ -2296,7 +2296,7 @@ void object_handle_update(Scene *scene, Object *ob) if(ob->recalc & OB_RECALC_DATA) { - // printf("recalcdata %s\n", ob->id.name+2); + printf("recalcdata %s\n", ob->id.name+2); /* includes all keys and modifiers */ if(ob->type==OB_MESH) { @@ -2312,29 +2312,20 @@ void object_handle_update(Scene *scene, Object *ob) else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { makeDispListCurveTypes(scene, ob, 0); } - else if(ob->type==OB_LATTICE) { - lattice_calc_modifiers(scene, ob); - } - else if(ob->type==OB_CAMERA) { - //Camera *cam = (Camera *)ob->data; - - // xxx old animation code here - //calc_ipo(cam->ipo, frame_to_float(scene, scene->r.cfra)); - //execute_ipo(&cam->id, cam->ipo); + else if(ELEM(ob->type, OB_CAMERA, OB_LAMP)) { + ID *data_id= (ID *)ob->data; + AnimData *adt= BKE_animdata_from_id(data_id); + float ctime= (float)scene->r.cfra; // XXX this is bad... - // in new system, this has already been done! - aligorith + /* evaluate drivers */ + BKE_animsys_evaluate_animdata(data_id, adt, ctime, ADT_RECALC_DRIVERS); } - else if(ob->type==OB_LAMP) { - //Lamp *la = (Lamp *)ob->data; - - // xxx old animation code here - //calc_ipo(la->ipo, frame_to_float(scene, scene->r.cfra)); - //execute_ipo(&la->id, la->ipo); - - // in new system, this has already been done! - aligorith + else if(ob->type==OB_LATTICE) { + lattice_calc_modifiers(scene, ob); } else if(ob->type==OB_ARMATURE) { /* this happens for reading old files and to match library armatures with poses */ + // XXX this won't screw up the pose set already... if(ob->pose==NULL || (ob->pose->flag & POSE_RECALC)) armature_rebuild_pose(ob, ob->data); @@ -2343,7 +2334,6 @@ void object_handle_update(Scene *scene, Object *ob) // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); } else { - //do_all_pose_actions(scene, ob); // xxx old animation system where_is_pose(scene, ob); } } diff --git a/source/blender/blenloader/SConscript b/source/blender/blenloader/SConscript index 5a445ad0cfc..1aeb6bd9b83 100644 --- a/source/blender/blenloader/SConscript +++ b/source/blender/blenloader/SConscript @@ -11,4 +11,4 @@ incs += ' ' + env['BF_ZLIB_INC'] defs = [] -env.BlenderLib ( 'bf_blenloader', sources, Split(incs), defs, libtype=['core','player'], priority = [165, 30] ) +env.BlenderLib ( 'bf_blenloader', sources, Split(incs), defs, libtype=['core','player'], priority = [135, 30] ) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b1ce482cbc5..23f22523e19 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -122,6 +122,7 @@ #include "BKE_global.h" // for G #include "BKE_group.h" #include "BKE_image.h" +#include "BKE_ipo.h" #include "BKE_key.h" //void set_four_ipo #include "BKE_lattice.h" #include "BKE_library.h" // for wich_libbase @@ -1823,6 +1824,7 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) } } +/* NOTE: this assumes that link_list has already been called on the list */ static void direct_link_fcurves(FileData *fd, ListBase *list) { FCurve *fcu; @@ -1904,8 +1906,8 @@ static void direct_link_action(FileData *fd, bAction *act) bActionChannel *achan; // XXX depreceated - old animation system bActionGroup *agrp; - link_list(fd, &act->curves); // xxx - do we need to patch the data for this? - link_list(fd, &act->chanbase); + link_list(fd, &act->curves); + link_list(fd, &act->chanbase); // XXX depreceated - old animation system link_list(fd, &act->groups); link_list(fd, &act->markers); @@ -1951,6 +1953,7 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) return; /* link drivers */ + link_list(fd, &adt->drivers); direct_link_fcurves(fd, &adt->drivers); /* link overrides */ @@ -8665,14 +8668,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 3)) { bScreen *sc; - Ipo *ipo; - IpoCurve *icu; - - /* fix IPO-curves to work with new interpolation options */ - //for (ipo=main->ipo.first; ipo; ipo= ipo->id.next) { - // for (icu= ipo->curve.first; icu; icu= icu->next) - // set_interpolation_ipocurve(icu, icu->ipo); // function removed (XXX add it here) - //} /* adjust default settings for Animation Editors */ for (sc= main->screen.first; sc; sc= sc->id.next) { @@ -8719,10 +8714,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for(screen= main->screen.first; screen; screen= screen->id.next) do_versions_windowmanager_2_50(screen); + /* old Animation System (using IPO's) needs to be converted to the new Animato system + * (NOTE: conversion code in blenkernel/intern/ipo.c for now) + */ + //do_versions_ipos_to_animato(main); + /* struct audio data moved to renderdata */ for(scene= main->scene.first; scene; scene= scene->id.next) { scene->r.audio = scene->audio; - + if(!scene->toolsettings->uv_selectmode) scene->toolsettings->uv_selectmode= UV_SELECT_VERTEX; } @@ -8836,7 +8836,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_material(fd, main); lib_link_texture(fd, main); lib_link_image(fd, main); - lib_link_ipo(fd, main); + lib_link_ipo(fd, main); // XXX depreceated... still needs to be maintained for version patches still lib_link_key(fd, main); lib_link_world(fd, main); lib_link_lamp(fd, main); @@ -9136,7 +9136,6 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt) /* own action */ expand_doit(fd, mainvar, adt->action); - expand_action(fd, mainvar, adt->action); // XXX this call is only used for patching old animation system /* drivers - assume that these F-Curves have driver data to be in this list... */ for (fcd= adt->drivers.first; fcd; fcd= fcd->next) { @@ -9167,6 +9166,9 @@ static void expand_group(FileData *fd, Main *mainvar, Group *group) static void expand_key(FileData *fd, Main *mainvar, Key *key) { expand_doit(fd, mainvar, key->ipo); // XXX depreceated - old animation system + + if(key->adt) + expand_animdata(fd, mainvar, key->adt); } static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 39a477f30fb..48b3bbb918c 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -1058,6 +1058,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar) } break; + case ANIMTYPE_FILLACTD: + case ANIMTYPE_FILLMATD: case ANIMTYPE_DSSKEY: { if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index c54ceba67f8..8b89c41775c 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -255,32 +255,15 @@ static float actcopy_firstframe= 999999999.0f; // XXX find some header to put this in! void free_actcopybuf () { -#if 0 // XXX old animation system - bActionChannel *achan, *anext; - bConstraintChannel *conchan, *cnext; + FCurve *fcu, *fcn; - for (achan= actcopybuf.first; achan; achan= anext) { - anext= achan->next; - - if (achan->ipo) { - free_ipo(achan->ipo); - MEM_freeN(achan->ipo); - } - - for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) { - cnext= conchan->next; - - if (conchan->ipo) { - free_ipo(conchan->ipo); - MEM_freeN(conchan->ipo); - } - - BLI_freelinkN(&achan->constraintChannels, conchan); - } - - BLI_freelinkN(&actcopybuf, achan); + /* free_fcurve() frees F-Curve memory too, but we don't need to do remlink first, as we're freeing all + * channels anyway, and the freeing func only cares about the data it's given + */ + for (fcu= actcopybuf.first; fcu; fcu= fcn) { + fcn= fcu->next; + free_fcurve(fcu); } -#endif // XXX old animation system actcopybuf.first= actcopybuf.last= NULL; actcopy_firstframe= 999999999.0f; @@ -292,7 +275,7 @@ void free_actcopybuf () * Only the selected action channels gets their selected keyframes copied. */ static short copy_action_keys (bAnimContext *ac) -{ +{ #if 0 // XXX old animation system ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index b1258e05f56..3731efb294c 100755 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -124,7 +124,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "loc"); RNA_def_property_ui_text(prop, "Location", ""); - prop= RNA_def_property(srna, "size", PROP_FLOAT, PROP_VECTOR); + prop= RNA_def_property(srna, "scale", PROP_FLOAT, PROP_VECTOR); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_ui_text(prop, "Scale", ""); |